Skip to content

Commit d688c76

Browse files
CzarekCzarek
authored andcommitted
Added Frame.GetFrameByIdentifier() in CEF 3.
Added Browser.GetFrames(), Frame.GetParent(), Frame.GetBrowser(). Added new callbacks to JavascriptContextHandler: OnContextCreated(), OnContextReleased() - both CEF 1 and CEF 3. Modified the implementation of the JavascriptBindings.Rebind() in CEF 1.
1 parent 0c6d477 commit d688c76

File tree

12 files changed

+239
-66
lines changed

12 files changed

+239
-66
lines changed

cefpython/browser.pyx

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,8 @@ cdef class PyBrowser:
152152
self.allowedClientCallbacks += ["OnKeyEvent"]
153153

154154
# CefV8ContextHandler.
155-
self.allowedClientCallbacks += ["OnUncaughtException"]
155+
self.allowedClientCallbacks += ["OnContextCreated",
156+
"OnContextReleased" ,"OnUncaughtException"]
156157

157158
# CefRequestHandler.
158159
self.allowedClientCallbacks += ["OnBeforeBrowse",
@@ -281,6 +282,11 @@ cdef class PyBrowser:
281282
PyToCefString(name, cefName)
282283
return GetPyFrame(self.GetCefBrowser().get().GetFrame(cefName))
283284

285+
IF CEF_VERSION == 3:
286+
cpdef object GetFrameByIdentifier(self, object identifier):
287+
return GetPyFrame(self.GetCefBrowser().get().GetFrame(
288+
<long long>long(identifier)))
289+
284290
cpdef list GetFrameNames(self):
285291
assert IsThread(TID_UI), (
286292
"Browser.GetFrameNames() may only be called on the UI thread")
@@ -295,6 +301,15 @@ cdef class PyBrowser:
295301
preinc(iterator)
296302
return names
297303

304+
cpdef list GetFrames(self):
305+
cdef list names = self.GetFrameNames()
306+
cdef PyFrame frame
307+
cdef list frames = []
308+
for name in names:
309+
frame = self.GetFrame(name)
310+
frames.append(frame)
311+
return frames
312+
298313
cpdef int GetIdentifier(self) except *:
299314
return self.GetCefBrowser().get().GetIdentifier()
300315

@@ -349,7 +364,6 @@ cdef class PyBrowser:
349364
return self.GetCefBrowser().get().HasDocument()
350365

351366
IF CEF_VERSION == 1:
352-
353367
cpdef py_void HidePopup(self):
354368
self.GetCefBrowser().get().HidePopup()
355369

@@ -360,7 +374,6 @@ cdef class PyBrowser:
360374
return self.GetCefBrowser().get().IsPopup()
361375

362376
IF CEF_VERSION == 1:
363-
364377
cpdef py_bool IsPopupVisible(self):
365378
assert IsThread(TID_UI), (
366379
"Browser.IsPopupVisible() may only be called on UI thread")

cefpython/cef3/client_handler/client_handler.cpp

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,47 @@
33
// Website: http://code.google.com/p/cefpython/
44

55
#include "client_handler.h"
6+
#include "cefpython_public_api.h"
67
#include <stdio.h>
78

9+
// Declared "inline" to get rid of the "already defined" errors when linking.
10+
inline void DebugLog(const char* szString)
11+
{
12+
// TODO: get the log_file option from CefSettings.
13+
FILE* pFile = fopen("debug.log", "a");
14+
fprintf(pFile, "cefpython_app: %s\n", szString);
15+
fclose(pFile);
16+
}
17+
818
bool ClientHandler::OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
919
CefProcessId source_process,
1020
CefRefPtr<CefProcessMessage> message) {
11-
std::string name = message.get()->GetName().ToString();
12-
printf("Browser: OnProcessMessageReceived(): %s\n", name.c_str());
21+
std::string messageName = message.get()->GetName().ToString();
22+
printf("Browser: OnProcessMessageReceived(): %s\n", messageName.c_str());
23+
if (messageName == "OnContextCreated") {
24+
CefRefPtr<CefListValue> args = message.get()->GetArgumentList();
25+
if (args.get()->GetSize() == 1
26+
&& args.get()->GetType(0) == VTYPE_INT) {
27+
int64 frameIdentifier = args.get()->GetInt(0);
28+
V8ContextHandler_OnContextCreated(browser, frameIdentifier);
29+
return true;
30+
} else {
31+
DebugLog("Browser: OnProcessMessageReceived(): invalid arguments,"\
32+
" messageName=OnContextCreated");
33+
return false;
34+
}
35+
} else if (messageName == "OnContextReleased") {
36+
CefRefPtr<CefListValue> args = message.get()->GetArgumentList();
37+
if (args.get()->GetSize() == 1
38+
&& args.get()->GetType(0) == VTYPE_INT) {
39+
int64 frameIdentifier = args.get()->GetInt(0);
40+
V8ContextHandler_OnContextReleased(browser, frameIdentifier);
41+
return true;
42+
} else {
43+
DebugLog("Browser: OnProcessMessageReceived(): invalid arguments,"\
44+
" messageName=OnContextReleased");
45+
return false;
46+
}
47+
}
1348
return false;
1449
}
Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,26 @@
1-
// nothing
1+
#ifndef __PYX_HAVE__cefpython_py27
2+
#define __PYX_HAVE__cefpython_py27
3+
4+
5+
#ifndef __PYX_HAVE_API__cefpython_py27
6+
7+
#ifndef __PYX_EXTERN_C
8+
#ifdef __cplusplus
9+
#define __PYX_EXTERN_C extern "C"
10+
#else
11+
#define __PYX_EXTERN_C extern
12+
#endif
13+
#endif
14+
15+
__PYX_EXTERN_C DL_IMPORT(void) V8ContextHandler_OnContextCreated(CefRefPtr<CefBrowser>, int64);
16+
__PYX_EXTERN_C DL_IMPORT(void) V8ContextHandler_OnContextReleased(CefRefPtr<CefBrowser>, int64);
17+
18+
#endif /* !__PYX_HAVE_API__cefpython_py27 */
19+
20+
#if PY_MAJOR_VERSION < 3
21+
PyMODINIT_FUNC initcefpython_py27(void);
22+
#else
23+
PyMODINIT_FUNC PyInit_cefpython_py27(void);
24+
#endif
25+
26+
#endif /* !__PYX_HAVE__cefpython_py27 */

cefpython/cef3/subprocess/cefpython_app.cpp

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
#include "util.h"
77
#include <stdio.h>
88

9-
void DebugLog(const char* szString)
9+
// Declared "inline" to get rid of the "already defined" errors when linking.
10+
inline void DebugLog(const char* szString)
1011
{
12+
// TODO: get the log_file option from CefSettings.
1113
FILE* pFile = fopen("debug.log", "a");
1214
fprintf(pFile, "cefpython_app: %s\n", szString);
1315
fclose(pFile);
@@ -97,14 +99,24 @@ void CefPythonApp::OnContextCreated(CefRefPtr<CefBrowser> browser,
9799
CefRefPtr<CefFrame> frame,
98100
CefRefPtr<CefV8Context> context) {
99101
DebugLog("OnContextCreated() called");
100-
CefRefPtr<CefProcessMessage> msg = CefProcessMessage::Create(
102+
CefRefPtr<CefProcessMessage> message = CefProcessMessage::Create(
101103
"OnContextCreated");
102-
browser.get()->SendProcessMessage(PID_BROWSER, msg);
104+
CefRefPtr<CefListValue> args = message.get()->GetArgumentList();
105+
// TODO: losing int64 precision
106+
args.get()->SetInt(0, (int)(frame.get()->GetIdentifier()));
107+
browser.get()->SendProcessMessage(PID_BROWSER, message);
103108
}
104109

105110
void CefPythonApp::OnContextReleased(CefRefPtr<CefBrowser> browser,
106111
CefRefPtr<CefFrame> frame,
107112
CefRefPtr<CefV8Context> context) {
113+
DebugLog("OnContextReleased() called");
114+
CefRefPtr<CefProcessMessage> message = CefProcessMessage::Create(
115+
"OnContextReleased");
116+
CefRefPtr<CefListValue> args = message.get()->GetArgumentList();
117+
// TODO: losing int64 precision
118+
args.get()->SetInt(0, (int)(frame.get()->GetIdentifier()));
119+
browser.get()->SendProcessMessage(PID_BROWSER, message);
108120
}
109121

110122
void CefPythonApp::OnUncaughtException(CefRefPtr<CefBrowser> browser,
@@ -131,3 +143,13 @@ bool CefPythonApp::OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
131143
printf("Renderer: OnProcessMessageReceived(): %s\n", name.c_str());
132144
return false;
133145
}
146+
147+
void DoJavascriptBindings(CefRefPtr<CefBrowser> browser,
148+
CefRefPtr<CefFrame> frame,
149+
CefRefPtr<CefV8Context> context) {
150+
151+
}
152+
153+
void RedoJavascriptBindings(CefRefPtr<CefBrowser> browser) {
154+
155+
}

cefpython/cef3/subprocess/main.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
#include "cefpython_app.h"
66

77
/*
8-
void DebugLog(const char* szString)
8+
// Declared "inline" to get rid of the "already defined" errors when linking.
9+
inline void DebugLog(const char* szString)
910
{
11+
// TODO: get the log_file option from CefSettings.
1012
FILE* pFile = fopen("debug.log", "a");
11-
fprintf(pFile, "%s\n",szString);
13+
fprintf(pFile, "cefpython_app: %s\n", szString);
1214
fclose(pFile);
1315
}
1416
*/

cefpython/cefpython.pyx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ IF CEF_VERSION == 1:
147147

148148
IF CEF_VERSION == 3:
149149
include "process_message_utils.pyx"
150+
include "v8context_handler_cef3.pyx"
150151

151152
# Try not to run any of the CEF code until Initialize() is called.
152153
# Do not allocate any memory on the heap until Initialize() is called,
@@ -241,13 +242,12 @@ def CreateBrowserSync(windowInfo, browserSettings, navigateUrl):
241242
cdef PyBrowser pyBrowser = GetPyBrowser(cefBrowser)
242243
pyBrowser.SetUserData("__outerWindowHandle", int(windowInfo.parentWindowHandle))
243244

244-
IF CEF_VERSION == 3:
245+
# IF CEF_VERSION == 3:
245246
# Test whether process message sent before renderer thread is created
246247
# will be delivered - OK.
247248
# Debug("Sending 'CreateBrowserSync() done' message to the Renderer")
248249
# assert pyBrowser.SendProcessMessage(cef_types.PID_RENDERER,
249250
# "CreateBrowserSync() done")
250-
pass
251251

252252
return pyBrowser
253253

cefpython/cython_includes/cef_browser.pxd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ from libcpp.vector cimport vector as cpp_vector
1313
from cef_frame cimport CefFrame
1414
cimport cef_types
1515
from cef_platform cimport CefKeyInfo
16+
from cef_types cimport int64
1617

1718
IF CEF_VERSION == 1:
1819
from cef_types_wrappers cimport CefRect
@@ -122,6 +123,7 @@ cdef extern from "include/cef_browser.h":
122123
cpp_bool CanGoForward()
123124
CefRefPtr[CefFrame] GetFocusedFrame()
124125
CefRefPtr[CefFrame] GetFrame(CefString& name)
126+
CefRefPtr[CefFrame] GetFrame(int64 identifier)
125127
void GetFrameNames(cpp_vector[CefString]& names)
126128
CefRefPtr[CefFrame] GetMainFrame()
127129
void GoBack()

cefpython/cython_includes/cef_frame.pxd

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ from cef_string cimport CefString
1010
from libcpp cimport bool as cpp_bool
1111
from cef_ptr cimport CefRefPtr
1212
from cef_v8 cimport CefV8Context
13+
from cef_browser cimport CefBrowser
1314

1415
cdef extern from "include/cef_frame.h":
1516

@@ -39,6 +40,8 @@ cdef extern from "include/cef_frame.h":
3940
cpp_bool IsFocused()
4041
CefString GetName()
4142
# virtual void VisitDOM(CefRefPtr<CefDOMVisitor> visitor) =0;
43+
CefRefPtr[CefFrame] GetParent()
44+
CefRefPtr[CefBrowser] GetBrowser()
4245

4346
ELIF CEF_VERSION == 3:
4447

@@ -65,5 +68,7 @@ cdef extern from "include/cef_frame.h":
6568
cpp_bool IsFocused()
6669
CefString GetName()
6770
# virtual void VisitDOM(CefRefPtr<CefDOMVisitor> visitor) =0;
71+
CefRefPtr[CefFrame] GetParent()
72+
CefRefPtr[CefBrowser] GetBrowser()
6873

6974

cefpython/imports.pyx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ from libc.stdlib cimport atoi
7070
from libc.stdint cimport uint64_t
7171
from libc.stdint cimport uintptr_t
7272

73+
# Also defined in cef_types.
74+
ctypedef long long int64
75+
7376
cimport ctime
7477

7578
IF UNAME_SYSNAME == "Windows":

cefpython/javascript_bindings.pyx

Lines changed: 55 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,11 @@ cdef class JavascriptBindings:
1010
cdef public dict properties
1111
cdef public dict objects
1212

13-
# V8ContextHandler_OnContextCreated inserts frames here that should have
14-
# javascript bindings, it is later needed to do rebinding using Rebind()
15-
# method. All frames are here, the main too, frames may be from different
16-
# Browser objects.
17-
cdef public dict frames # frameIdentifier(int64) : tuple(PyBrowser, PyFrame())
18-
1913
def __init__(self, bindToFrames=False, bindToPopups=False):
2014
self.functions = {}
2115
self.properties = {}
2216
self.objects = {}
23-
self.frames = {}
24-
17+
2518
self.bindToFrames = int(bindToFrames)
2619
self.bindToPopups = int(bindToPopups)
2720

@@ -78,41 +71,60 @@ cdef class JavascriptBindings:
7871
else:
7972
self.properties[name] = value
8073

81-
cdef py_void AddFrame(self, PyBrowser pyBrowser, PyFrame pyFrame):
82-
if pyFrame.GetIdentifier() not in self.frames:
83-
self.frames[pyFrame.GetIdentifier()] = (pyBrowser, pyFrame)
84-
85-
cdef py_void RemoveFrame(self, PyBrowser pyBrowser, PyFrame pyFrame):
86-
if pyFrame.GetIdentifier() in self.frames:
87-
del self.frames[pyFrame.GetIdentifier()]
88-
89-
cpdef py_void Rebind(self):
90-
assert IsThread(TID_UI), (
91-
"JavascriptBindings.Rebind() may only be called on UI thread")
92-
93-
cdef CefRefPtr[CefBrowser] cefBrowser
94-
cdef CefRefPtr[CefFrame] cefFrame
95-
cdef CefRefPtr[CefV8Context] v8Context
96-
cdef cpp_bool sameContext
97-
cdef PyBrowser pyBrowser
98-
cdef PyFrame pyFrame
99-
100-
for frameId in self.frames:
101-
pyBrowser = self.frames[frameId][0]
102-
pyFrame = self.frames[frameId][1]
103-
cefBrowser = pyBrowser.GetCefBrowser()
104-
cefFrame = pyFrame.GetCefFrame()
105-
v8Context = cefFrame.get().GetV8Context()
106-
107-
sameContext = v8Context.get().IsSame(cef_v8_static.GetCurrentContext())
108-
if not sameContext:
109-
Debug("JavascriptBindings.Rebind(): inside a different context, calling v8Context.Enter()")
110-
assert v8Context.get().Enter(), "v8Context.Enter() failed"
111-
112-
V8ContextHandler_OnContextCreated(cefBrowser, cefFrame, v8Context)
113-
114-
if not sameContext:
115-
assert v8Context.get().Exit(), "v8Context.Exit() failed"
74+
75+
IF CEF_VERSION == 1:
76+
cpdef py_void Rebind(self):
77+
# Rebind may also be used for first-time bindings, in
78+
# a case when v8 process/thread was created too fast,
79+
# see Browser.SetJavascriptBindings() that checks whether
80+
# OnContextCreated() event already happened, if so it will
81+
# call Rebind() to do the javascript bindings.
82+
assert IsThread(TID_UI), (
83+
"JavascriptBindings.Rebind() may only be called on UI thread")
84+
cdef CefRefPtr[CefBrowser] cefBrowser
85+
cdef CefRefPtr[CefFrame] cefFrame
86+
cdef CefRefPtr[CefV8Context] v8Context
87+
cdef cpp_bool sameContext
88+
cdef PyBrowser pyBrowser
89+
cdef PyFrame pyFrame
90+
cdef list frames
91+
global g_pyBrowsers
92+
for pyBrowser in g_pyBrowsers:
93+
# These javascript bindings may have been binded
94+
# to many browsers.
95+
if pyBrowser.GetJavascriptBindings() != self:
96+
continue
97+
if self.bindToFrames:
98+
frames = pyBrowser.GetFrames()
99+
else:
100+
frames = [pyBrowser.GetMainFrame()]
101+
for frameId in self.frames:
102+
pyBrowser = self.frames[frameId][0]
103+
pyFrame = self.frames[frameId][1]
104+
cefBrowser = pyBrowser.GetCefBrowser()
105+
cefFrame = pyFrame.GetCefFrame()
106+
v8Context = cefFrame.get().GetV8Context()
107+
sameContext = v8Context.get().IsSame(cef_v8_static.GetCurrentContext())
108+
if not sameContext:
109+
Debug("JavascriptBindings.Rebind(): inside a different context, calling v8Context.Enter()")
110+
assert v8Context.get().Enter(), "v8Context.Enter() failed"
111+
V8ContextHandler_OnContextCreated(cefBrowser, cefFrame, v8Context)
112+
if not sameContext:
113+
assert v8Context.get().Exit(), "v8Context.Exit() failed"
114+
115+
ELIF CEF_VERSION == 3:
116+
cpdef py_void Rebind(self):
117+
# Rebind may also be used for first-time bindings, in
118+
# a case when v8 process/thread was created too fast,
119+
# see Browser.SetJavascriptBindings() that checks whether
120+
# OnContextCreated() event already happened, if so it will
121+
# call Rebind() to do the javascript bindings.
122+
cdef PyBrowser pyBrowser
123+
global g_pyBrowsers
124+
for pyBrowser in g_pyBrowsers:
125+
# Send to renderer process: properties, functions,
126+
# objects and its methods, bindToFrames.
127+
pass
116128

117129
cpdef dict GetProperties(self):
118130
return self.properties

0 commit comments

Comments
 (0)