Skip to content

Commit 0f58a3e

Browse files
CzarekCzarek
authored andcommitted
CEF 3 javascript bindings not yet complete. Still todo: passing
function arguments, binding objects and properties.
1 parent e234b00 commit 0f58a3e

10 files changed

Lines changed: 150 additions & 40 deletions

File tree

cefpython/cef3/cefpython_public_api.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
// To be able to use 'public' declarations you need to include Python.h and cefpython.h.
88
// This include must be before including CEF, otherwise you get errors like:
99
// | /usr/include/python2.7/pyconfig.h:1161:0: warning: "_POSIX_C_SOURCE" redefined
10+
// This file needs to be included first before CEF.
1011
#include "Python.h"
1112

1213
// All the imports that are required when including "cefpython.h".

cefpython/cef3/client_handler/client_handler.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,12 @@ bool ClientHandler::OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
5353
if (args->GetSize() == 3
5454
&& args->GetType(0) == VTYPE_INT // frameId
5555
&& args->GetType(1) == VTYPE_STRING // funcName
56-
&& args->GetType(2) == VTYPE_LIST) { // funcArgs
56+
&& args->GetType(2) == VTYPE_LIST) { // funcArguments
5757
int64 frameId = args->GetInt(0);
58-
CefRefPtr<CefFrame> frame = browser->GetFrame(frameId);
5958
CefString funcName = args->GetString(1);
60-
CefRefPtr<CefListValue> funcArgs = args->GetList(2);
61-
V8FunctionHandler_Execute(browser, frame, funcName, funcArgs);
59+
CefRefPtr<CefListValue> funcArguments = args->GetList(2);
60+
CefRefPtr<CefFrame> frame = browser->GetFrame(frameId);
61+
V8FunctionHandler_Execute(browser, frame, funcName, funcArguments);
6262
return true;
6363
} else {
6464
DebugLog("Browser: OnProcessMessageReceived(): invalid arguments," \

cefpython/cef3/linux/binaries_64bit/wxpython.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ <h3>HTML5 video and accelerated content</h3>
4141

4242

4343
<h3>Javascript bindings</h3>
44-
<a href="javascript:external.Print('printing in python console from js')">
45-
external.Print('printing in python console from js')</a>
44+
<a href="javascript:PyPrint('printing in python console from js')">
45+
PyPrint('printing in python console from js')</a>
4646

4747

4848

cefpython/cef3/linux/binaries_64bit/wxpython.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ def __init__(self):
106106

107107
jsBindings = cefpython.JavascriptBindings(
108108
bindToFrames=False, bindToPopups=False)
109+
jsBindings.SetFunction("PyPrint", PyPrint)
109110
jsBindings.SetObject("external", JavascriptBindings(self.browser))
110111
self.browser.SetJavascriptBindings(jsBindings)
111112

@@ -133,6 +134,9 @@ def OnClose(self, event):
133134
def OnIdle(self, event):
134135
cefpython.MessageLoopWork()
135136

137+
def PyPrint(message):
138+
print(message)
139+
136140
class JavascriptBindings:
137141
mainBrowser = None
138142

cefpython/cef3/subprocess/cefpython_app.cpp

Lines changed: 81 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,8 @@ void CefPythonApp::OnContextCreated(CefRefPtr<CefBrowser> browser,
144144
if (frame->IsMain()) {
145145
DoJavascriptBindingsForFrame(browser, frame, context);
146146
} else {
147-
if (jsBindings->GetType("bindToFrames") == VTYPE_BOOL
147+
if (jsBindings->HasKey("bindToFrames")
148+
&& jsBindings->GetType("bindToFrames") == VTYPE_BOOL
148149
&& jsBindings->GetBool("bindToFrames")) {
149150
DoJavascriptBindingsForFrame(browser, frame, context);
150151
}
@@ -231,6 +232,52 @@ void CefPythonApp::RemoveJavascriptBindings(CefRefPtr<CefBrowser> browser) {
231232
}
232233
}
233234

235+
bool CefPythonApp::BindedFunctionExists(CefRefPtr<CefBrowser> browser,
236+
const CefString& funcName) {
237+
CefRefPtr<CefDictionaryValue> jsBindings = GetJavascriptBindings(browser);
238+
if (!jsBindings.get()) {
239+
return false;
240+
}
241+
std::string strFuncName = funcName.ToString();
242+
size_t dotPosition = strFuncName.find(".");
243+
if (std::string::npos != dotPosition) {
244+
// This is a method call, funcName == "object.method".
245+
CefString objectName(strFuncName.substr(0, dotPosition));
246+
CefString methodName(strFuncName.substr(dotPosition, std::string::npos));
247+
if (!(jsBindings->HasKey("objects")
248+
&& jsBindings->GetType("objects") == VTYPE_DICTIONARY)) {
249+
DebugLog("Renderer: BindedFunctionExists() FAILED: "\
250+
"objects dictionary not found");
251+
return false;
252+
}
253+
CefRefPtr<CefDictionaryValue> objects = \
254+
jsBindings->GetDictionary("objects");
255+
if (objects->HasKey(objectName)) {
256+
if (!(objects->GetType(objectName) == VTYPE_DICTIONARY)) {
257+
DebugLog("Renderer: BindedFunctionExists() FAILED: "\
258+
"objects dictionary has invalid type");
259+
return false;
260+
}
261+
CefRefPtr<CefDictionaryValue> methods = \
262+
objects->GetDictionary(objectName);
263+
return methods->HasKey(methodName);
264+
} else {
265+
return false;
266+
}
267+
} else {
268+
// This is a function call.
269+
if (!(jsBindings->HasKey("functions")
270+
&& jsBindings->GetType("functions") == VTYPE_DICTIONARY)) {
271+
DebugLog("Renderer: BindedFunctionExists() FAILED: "\
272+
"functions dictionary not found");
273+
return false;
274+
}
275+
CefRefPtr<CefDictionaryValue> functions = \
276+
jsBindings->GetDictionary("functions");
277+
return functions->HasKey(funcName);
278+
}
279+
}
280+
234281
void CefPythonApp::DoJavascriptBindingsForBrowser(
235282
CefRefPtr<CefBrowser> browser) {
236283
// get frame
@@ -246,7 +293,8 @@ void CefPythonApp::DoJavascriptBindingsForBrowser(
246293
return;
247294
}
248295
std::vector<int64> frameIds;
249-
if (jsBindings->GetType("bindToFrames") == VTYPE_BOOL
296+
if (jsBindings->HasKey("bindToFrames")
297+
&& jsBindings->GetType("bindToFrames") == VTYPE_BOOL
250298
&& jsBindings->GetBool("bindToFrames")) {
251299
browser->GetFrameIdentifiers(frameIds);
252300
} else {
@@ -277,16 +325,28 @@ void CefPythonApp::DoJavascriptBindingsForFrame(CefRefPtr<CefBrowser> browser,
277325
return;
278326
}
279327
DebugLog("Renderer: DoJavascriptBindingsForFrame(): bindings are set");
280-
if (!(jsBindings->GetType("functions") == VTYPE_LIST
328+
if (!(jsBindings->HasKey("functions")
329+
&& jsBindings->GetType("functions") == VTYPE_DICTIONARY
330+
&& jsBindings->HasKey("properties")
281331
&& jsBindings->GetType("properties") == VTYPE_DICTIONARY
332+
&& jsBindings->HasKey("objects")
282333
&& jsBindings->GetType("objects") == VTYPE_DICTIONARY
334+
&& jsBindings->HasKey("bindToFrames")
283335
&& jsBindings->GetType("bindToFrames") == VTYPE_BOOL)) {
284336
DebugLog("Renderer: DoJavascriptBindingsForFrame() FAILED: " \
285337
"invalid data [1]");
286338
return;
287339
}
340+
// A context must be explicitly entered before creating a
341+
// V8 Object, Array, Function or Date asynchronously.
342+
bool enteredContext = false;
343+
if (!context->IsSame(CefV8Context::GetCurrentContext())) {
344+
enteredContext = true;
345+
context->Enter();
346+
}
288347
// TODO: properties, objects, other frames.
289-
CefRefPtr<CefListValue> functions = jsBindings->GetList("functions");
348+
CefRefPtr<CefDictionaryValue> functions = \
349+
jsBindings->GetDictionary("functions");
290350
CefRefPtr<CefDictionaryValue> properties = \
291351
jsBindings->GetDictionary("properties");
292352
CefRefPtr<CefDictionaryValue> objects = \
@@ -297,20 +357,29 @@ void CefPythonApp::DoJavascriptBindingsForFrame(CefRefPtr<CefBrowser> browser,
297357
&& objects->IsValid())) {
298358
DebugLog("Renderer: DoJavascriptBindingsForFrame() FAILED: " \
299359
"invalid data [2]");
360+
if (enteredContext)
361+
context->Exit();
300362
return;
301363
}
302364
CefRefPtr<CefV8Value> v8Window = context->GetGlobal();
303365
CefRefPtr<CefV8Value> v8Function;
366+
CefRefPtr<CefV8Handler> v8FunctionHandler(new V8FunctionHandler(this));
304367
// FUNCTIONS.
305-
for (unsigned int i = 0; i < functions->GetSize(); i++) {
306-
if (functions->GetType(i) != VTYPE_STRING) {
307-
DebugLog("Renderer: DoJavascriptBindingsForFrame() FAILED: " \
308-
"invalid data [3]");
309-
return;
310-
}
311-
CefString funcName = functions->GetString(i);
312-
v8Function = CefV8Value::CreateFunction(funcName, v8FunctionHandler_);
368+
std::vector<CefString> functionsVector;
369+
if (!functions->GetKeys(functionsVector)) {
370+
DebugLog("Renderer: DoJavascriptBindingsForFrame(): " \
371+
"functions->GetKeys() FAILED");
372+
if (enteredContext)
373+
context->Exit();
374+
return;
375+
}
376+
for (std::vector<CefString>::iterator it = functionsVector.begin(); \
377+
it != functionsVector.end(); ++it) {
378+
CefString funcName = *it;
379+
v8Function = CefV8Value::CreateFunction(funcName, v8FunctionHandler);
313380
v8Window->SetValue(funcName, v8Function,
314381
V8_PROPERTY_ATTRIBUTE_NONE);
315382
}
383+
if (enteredContext)
384+
context->Exit();
316385
}

cefpython/cef3/subprocess/cefpython_app.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ class CefPythonApp :
2424
public CefBrowserProcessHandler,
2525
public CefRenderProcessHandler {
2626
public:
27-
CefPythonApp()
28-
: v8FunctionHandler_(new V8FunctionHandler()) {
27+
CefPythonApp() {
2928
}
3029

3130
virtual void OnBeforeCommandLineProcessing(
@@ -118,17 +117,18 @@ class CefPythonApp :
118117

119118
virtual void RemoveJavascriptBindings(CefRefPtr<CefBrowser> browser) OVERRIDE;
120119

120+
virtual bool BindedFunctionExists(CefRefPtr<CefBrowser> browser,
121+
const CefString& funcName) OVERRIDE;
122+
121123
virtual void DoJavascriptBindingsForBrowser(CefRefPtr<CefBrowser> browser)
122124
OVERRIDE;
123125

124126
virtual void DoJavascriptBindingsForFrame(CefRefPtr<CefBrowser> browser,
125127
CefRefPtr<CefFrame> frame,
126128
CefRefPtr<CefV8Context> context) OVERRIDE;
127129

128-
129130
protected:
130131
std::map<int, CefRefPtr<CefDictionaryValue> > javascriptBindings_;
131-
CefRefPtr<CefV8Handler> v8FunctionHandler_;
132132

133133
private:
134134
// Include the default reference counting implementation.

cefpython/cef3/subprocess/v8function_handler.cpp

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
// License: New BSD License.
33
// Website: http://code.google.com/p/cefpython/
44

5+
#include "cefpython_public_api.h"
56
#include "v8function_handler.h"
7+
#include "v8utils.h"
8+
#include "cefpython_app.h"
69

710
// Defined as "inline" to get rid of the "already defined" errors
811
// when linking.
@@ -15,17 +18,29 @@ inline void DebugLog(const char* szString)
1518
fclose(pFile);
1619
}
1720

18-
bool V8FunctionHandler::Execute(const CefString& name,
21+
bool V8FunctionHandler::Execute(const CefString& funcName,
1922
CefRefPtr<CefV8Value> object,
20-
const CefV8ValueList& arguments,
23+
const CefV8ValueList& v8Arguments,
2124
CefRefPtr<CefV8Value>& retval,
2225
CefString& exception) {
23-
DebugLog("V8FunctionHandler::Execute()");
26+
DebugLog("Renderer: V8FunctionHandler::Execute()");
2427
CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
2528
CefRefPtr<CefBrowser> browser = context.get()->GetBrowser();
26-
CefRefPtr<CefFrame> frame = context.get()->GetFrame();
27-
// convert arguments to CefListValue
28-
// set retval to null
29-
// send process message: frameId, funcName, funcArgs
30-
return false;
29+
CefRefPtr<CefFrame> frame = context.get()->GetFrame();
30+
if (!cefPythonApp_->BindedFunctionExists(browser, funcName)) {
31+
return false;
32+
}
33+
CefRefPtr<CefListValue> funcArguments = V8ValueListToCefListValue(
34+
v8Arguments);
35+
// TODO: losing int64 precision here.
36+
int frameId = (int)frame->GetIdentifier();
37+
CefRefPtr<CefProcessMessage> processMessage = CefProcessMessage::Create(
38+
"V8FunctionHandler::Execute");
39+
CefRefPtr<CefListValue> messageArguments = processMessage->GetArgumentList();
40+
messageArguments->SetInt(0, frameId);
41+
messageArguments->SetString(1, funcName);
42+
messageArguments->SetList(2, funcArguments);
43+
browser->SendProcessMessage(PID_BROWSER, processMessage);
44+
retval = CefV8Value::CreateNull();
45+
return true;
3146
}

cefpython/cef3/subprocess/v8function_handler.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,26 @@
22
// License: New BSD License.
33
// Website: http://code.google.com/p/cefpython/
44

5+
#pragma once
6+
57
#include "include/cef_v8.h"
68
#include "util.h"
79

10+
class CefPythonApp;
11+
812
class V8FunctionHandler
913
: public CefV8Handler {
1014
public:
15+
V8FunctionHandler(CefRefPtr<CefPythonApp> cefPythonApp)
16+
: cefPythonApp_(cefPythonApp) {
17+
}
1118
virtual bool Execute(const CefString& name,
1219
CefRefPtr<CefV8Value> object,
1320
const CefV8ValueList& arguments,
1421
CefRefPtr<CefV8Value>& retval,
1522
CefString& exception) OVERRIDE;
23+
protected:
24+
CefRefPtr<CefPythonApp> cefPythonApp_;
1625
private:
1726
IMPLEMENT_REFCOUNTING(V8FunctionHandler);
1827
};
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright (c) 2012-2013 The CEF Python authors. All rights reserved.
2+
// License: New BSD License.
3+
// Website: http://code.google.com/p/cefpython/
4+
5+
#include "include/cef_v8.h"
6+
#include "include/cef_values.h"
7+
8+
CefRefPtr<CefListValue> V8ValueListToCefListValue(
9+
const CefV8ValueList& v8List) {
10+
// TODO.
11+
return CefListValue::Create();
12+
}

cefpython/javascript_bindings.pyx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
cdef class JavascriptBindings:
66
# By default binding only to top frame.
7-
cdef public int bindToFrames
8-
cdef public int bindToPopups
7+
cdef public cpp_bool bindToFrames
8+
cdef public cpp_bool bindToPopups
99
cdef public dict functions
1010
cdef public dict properties
1111
cdef public dict objects
@@ -15,8 +15,8 @@ cdef class JavascriptBindings:
1515
self.properties = {}
1616
self.objects = {}
1717

18-
self.bindToFrames = int(bindToFrames)
19-
self.bindToPopups = int(bindToPopups)
18+
self.bindToFrames = bool(bindToFrames)
19+
self.bindToPopups = bool(bindToPopups)
2020

2121
cpdef py_bool GetBindToFrames(self):
2222
return bool(self.bindToFrames)
@@ -116,23 +116,23 @@ cdef class JavascriptBindings:
116116
# In CEF Python 3 due to its multi-process architecture
117117
# Rebind() is used for both first-time binding and rebinding.
118118
cdef PyBrowser pyBrowser
119-
cdef list functions
119+
cdef dict functions
120120
cdef dict properties
121121
cdef dict objects
122-
cdef list methods
122+
cdef dict methods
123123
global g_pyBrowsers
124124
for browserId, pyBrowser in g_pyBrowsers.iteritems():
125125
# Send to the Renderer process: functions, properties,
126126
# objects and its methods, bindToFrames.
127-
functions = []
127+
functions = {}
128128
for funcName in self.functions:
129-
functions.append(funcName)
129+
functions[funcName] = None
130130
properties = self.properties
131131
objects = {}
132132
for objectName in self.objects:
133-
methods = []
133+
methods = {}
134134
for methodName in self.objects[objectName]:
135-
methods.append(methodName)
135+
methods[methodName] = None
136136
pyBrowser.SendProcessMessage(cef_types.PID_RENDERER,
137137
"DoJavascriptBindings", [{
138138
"functions": functions,

0 commit comments

Comments
 (0)