Hi,
I just uploaded a new version of CEF4Delphi and now the code comments in the JSExtension demo are a lot longer.
Here you have a copy with some text formatting :
BASIC CONCEPTS
Chromium uses several processes to carry out all the tasks needed to handle a web page :
- 1. The main application process is called "BROWSER PROCESS" and it runs the UI.
- 2. The layout and interpretation of HTML is done in the "RENDERER PROCESS".
Read this for more details about Chromium's architecture :
http://www.chromium.org/developers/desi ... chitecture
Each process is isolated from the rest and you need to use some kind of inter-process communication (IPC) to send information between them. This isolation and protection is guaranteed by the operating system and it's the main reason Chromium uses several processes.
In many cases, you need to use JavaScript or visit the DOM to return some results to Delphi. The DOM and JavaScript live in the RENDERER PROCESS, while the Delphi code of your application lives in the BROWSER PROCESS.
As commented before, the operating system isolates each process and this means that you can't access anything declared in one process like variables, fields, classes, controls, etc. from a different process.
However, CEF has several ways to send information between processes and you can also use your own inter-process communication methods.
If you need to execute some JavaScript code all you need is to call TChromium.ExecuteJavaScript from your application's code in the BROWSER PROCESS and CEF will take care of executing that code in the RENDERER PROCESS.
If you need to send a message to the RENDERER PROCESS from the BROWSER PROCESS you can use TChromium.SendProcessMessage.
To send messages to the BROWSER PROCESS from the RENDERER PROCESS you can use ICefFrame.SendProcessMessage
Code: Select all
-------------- TChromium.SendProcessMessage --------------
| | ------------------------------> | |
| BROWSER | | RENDERER |
| | | |
| PROCESS | ICefFrame.SendProcessMessage | PROCESS |
| | <------------------------------ | |
-------------- --------------
To receive the messages sent from the RENDERER PROCESS you need to use the TChromium.OnProcessMessageReceived event. This event is executed in a CEF thread that belongs to the BROWSER PROCESS.
To receive the messages sent from the BROWSER PROCESS you need to use the TCefApplication.OnProcessMessageReceived event (GlobalCEFApp.OnProcessMessageReceived). This event is executed in a CEF thread that belongs to the RENDERER PROCESS.
JAVASCRIPT EXTENSIONS
CEF exposes a large number of JS features for integration in client applications. You can use JS types, arrays, functions, extensions, objects, etc.
All of those features are described in detail here :
https://bitbucket.org/chromiumembedded/ ... gration.md
One of the most interesting JS features available in CEF are the JavaScript extensions because they can be used to execute custom Delphi code from JavaScript.
If you put all you know so far together you can get any result or information in Delphi from JavaScript following these steps :
- 1. Use TChromium.ExecuteJavaScript to execute your custom JavaScript code.
- 2. That custom JavaScript code is executed in the RENDERER PROCESS and it can call functions in your custom JavaScript extension, which executes Delphi code. This Delphi code is also executed in the RENDERER PROCESS.
- 3. The Delphi code in the JavaScript extension can use ICefFrame.SendProcessMessage to send information back to the BROWSER PROCESS.
- 4. The BROWSER PROCESS receives the information in the TChromium.OnProcessMessageReceived event.
To create a JavaScript extension in CEF you have to create a new class that inherits from TCefv8HandlerOwn and it has to override the "execute" function. Open uTestExtensionHandler.pas to see an example and read this for more details about the "execute" parameters :
https://magpcss.org/ceforum/apidocs3/pr ... ndler.html
In order to use that extension, you must reister it in the GlobalCEFApp.OnWebKitInitialized event as you can see in the GlobalCEFApp_OnWebKitInitialized procedure on this PAS unit.
You have to call the CefRegisterExtension function with 3 parameters :
- 1. name : The extension name.
- 2. code : Any valid JS code but in this case it includes 2 "native function" forward declarations.
- 3. Handler : An instance of your TCefv8HandlerOwn subclass.
Notice that the code used with the CefRegisterExtension function in this demo is declaring "myextension.mouseover" as a function that calls the "mouseover" native function, and the "myextension.sendresulttobrowser" function that calls the "sendresulttobrowser" native function.
The "execute" function in the custom TCefv8HandlerOwn subclass will compare the "name" parameter with the name of the of the native function used in the code that registered this extension. As you can see in this demo, TTestExtensionHandler.Execute compares the "name" parameter with
"mouseover" and "sendresulttobrowser" to execute the code you want for each of those custom functions.
TTestExtensionHandler.Execute is executed in the RENDERER PROCESS and it uses a process message to send some results to he BROWSER PROCESS.
It uses TCefv8ContextRef.Current.Browser.MainFrame to call the SendProcessMessage procedure for the main frame.
The message is a TCefProcessMessageRef instance and you can set the information you want to send using its ArgumentList property.
You can add several items to ArgumentList using different indexes in the SetString, SetInt, SetBool, SetBinary, etc. functions.
There is a size limit in the binary parameters of only a few kilobytes. Compress the binary data, use alternative IPC methods or use a database protected by a mutex if necessary.
For more information about this, read the following pages :
https://bitbucket.org/chromiumembedded/ ... extensions
https://bitbucket.org/chromiumembedded/ ... #lines-924