1
0
mirror of https://github.com/salvadordf/CEF4Delphi.git synced 2025-04-27 07:02:21 +02:00

Update to CEF 76.1.13

Added more code comments to the JSExtension demo
This commit is contained in:
Salvador Díaz Fau 2019-08-31 17:17:55 +02:00
parent 2507e0730b
commit be14dc6f33
12 changed files with 340 additions and 92 deletions

View File

@ -3,10 +3,10 @@ CEF4Delphi is an open source project created by Salvador D
CEF4Delphi is based on DCEF3, made by Henri Gourvest. The original license of DCEF3 still applies to CEF4Delphi. Read the license terms in the first lines of any *.pas file. CEF4Delphi is based on DCEF3, made by Henri Gourvest. The original license of DCEF3 still applies to CEF4Delphi. Read the license terms in the first lines of any *.pas file.
CEF4Delphi uses CEF 76.1.11 which includes Chromium 76.0.3809.132. CEF4Delphi uses CEF 76.1.13 which includes Chromium 76.0.3809.132.
The CEF binaries used by CEF4Delphi are available for download at spotify : The CEF binaries used by CEF4Delphi are available for download at spotify :
* [32 bits](http://opensource.spotify.com/cefbuilds/cef_binary_76.1.11%2Bgdc028ce%2Bchromium-76.0.3809.132_windows32.tar.bz2) * [32 bits](http://opensource.spotify.com/cefbuilds/cef_binary_76.1.13%2Bgf19c584%2Bchromium-76.0.3809.132_windows32.tar.bz2)
* [64 bits](http://opensource.spotify.com/cefbuilds/cef_binary_76.1.11%2Bgdc028ce%2Bchromium-76.0.3809.132_windows64.tar.bz2) * [64 bits](http://opensource.spotify.com/cefbuilds/cef_binary_76.1.13%2Bgf19c584%2Bchromium-76.0.3809.132_windows64.tar.bz2)
CEF4Delphi was developed and tested on Delphi 10.3 Rio and it has been tested in Delphi 7, Delphi XE, Delphi 10, Delphi 10.2 and Lazarus 2.0.4/FPC 3.0.4. CEF4Delphi includes VCL, FireMonkey (FMX) and Lazarus components. CEF4Delphi was developed and tested on Delphi 10.3 Rio and it has been tested in Delphi 7, Delphi XE, Delphi 10, Delphi 10.2 and Lazarus 2.0.4/FPC 3.0.4. CEF4Delphi includes VCL, FireMonkey (FMX) and Lazarus components.

View File

@ -127,53 +127,146 @@ implementation
uses uses
uSimpleTextViewer, uCEFMiscFunctions, uTestExtensionHandler; uSimpleTextViewer, uCEFMiscFunctions, uTestExtensionHandler;
// To test this demo follow these steps : // 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/design-documents/multi-process-architecture
// 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
// -------------- 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/cef/wiki/JavaScriptIntegration.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/projects/(default)/CefV8Handler.html
// In order to use that extension, you must register 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/cef/wiki/JavaScriptIntegration.md#markdown-header-functions-and-extensions
// https://bitbucket.org/chromiumembedded/cef/src/b6b033a52bb3f7059d169a4c8389966c8fe2531b/include/capi/cef_v8_capi.h#lines-924
// TESTING THIS DEMO :
// ===================
// 1. Run the demo and wait until google.com is loaded // 1. Run the demo and wait until google.com is loaded
// 2. Right-click and select the "Set the mouseover event" menu option. // 2. Right-click and select the "Set the mouseover event" menu option.
// 3. Move the mouse pointer over the web page and see the HTML elements in the status bar. // 3. Move the mouse pointer over the web page and see the HTML elements in the status bar.
// The CEF3 document describing extensions is here : // When you select the "Set the mouseover event" menu option, the
// https://bitbucket.org/chromiumembedded/cef/wiki/JavaScriptIntegration.md
// The Chromium project document describing Chromium's architecture is here :
// http://www.chromium.org/developers/design-documents/multi-process-architecture
// This demo has a JavaScript extension class that is registered in the
// GlobalCEFApp.OnWebKitInitialized event when the application is initializing.
// The extension in this demo is called "myextension" and it has 2 functions called
// "mouseover" and "sendresulttobrowser".
// When the JavaScript code uses those functions it executes the TTestExtensionHandler.Execute
// function in uTestExtensionHandler.pas.
// When you run this demo and you select the "Set the mouseover event" menu option, the
// TChromium.OnContextMenuCommand event is triggered and it adds an event listener to the // TChromium.OnContextMenuCommand event is triggered and it adds an event listener to the
// document's body. That listener calls one of the functions available in the registered // document's body. That listener calls one of the functions available in the registered
// extension called "myextension.mouseover". // extension called "myextension.mouseover".
// The TTestExtensionHandler.Execute function is executed in the renderer process and it // The TTestExtensionHandler.Execute function in the extension is executed and it
// can use the TCefv8ContextRef.Current.Browser.MainFrame.SendProcessMessage(PID_BROWSER, msg) function // uses TCefv8ContextRef.Current.Browser.MainFrame.SendProcessMessage(PID_BROWSER, msg)
// to send a message with the results to the browser process. // to send a process message with the results to the browser process.
// TCefv8ContextRef.Current returns the v8 context for the frame that is currently // That message is received in the TChromium.OnProcessMessageReceived event and it shows
// executing JavaScript, TCefv8ContextRef.Current.Browser.MainFrame.SendProcessMessage sends a message // the information in the status bar.
// to the right browser even if you have created several browsers in one app.
// That message is received in the TChromium.OnProcessMessageReceived event.
// Even if you create several TChromium objects you should have no problem because each of
// them will have its own TChromium.OnProcessMessageReceived event to receive the messages
// from the extension.
// TChromium.OnProcessMessageReceived receives that message and shows the information in
// the status bar.
// If you have to debug the code executed by the extension you will need to use the // If you have to debug the code executed by the extension you will need to use the
// debugging methods described in // debugging methods described in
// https://www.briskbard.com/index.php?lang=en&pageid=cef // https://www.briskbard.com/index.php?lang=en&pageid=cef
// Destruction steps
// DESTRUCTION STEPS
// ================= // =================
// 1. FormCloseQuery sets CanClose to FALSE calls TChromium.CloseBrowser which triggers // 1. FormCloseQuery sets CanClose to FALSE calls TChromium.CloseBrowser which triggers
// the TChromium.OnClose event. // the TChromium.OnClose event.
@ -181,6 +274,7 @@ uses
// in the main thread, which triggers the TChromium.OnBeforeClose event. // in the main thread, which triggers the TChromium.OnBeforeClose event.
// 3. TChromium.OnBeforeClose sets FCanClose := True and sends WM_CLOSE to the form. // 3. TChromium.OnBeforeClose sets FCanClose := True and sends WM_CLOSE to the form.
procedure GlobalCEFApp_OnWebKitInitialized; procedure GlobalCEFApp_OnWebKitInitialized;
var var
TempExtensionCode : string; TempExtensionCode : string;

View File

@ -166,13 +166,13 @@
</Excluded_Packages> </Excluded_Packages>
</Delphi.Personality> </Delphi.Personality>
<Deployment Version="3"> <Deployment Version="3">
<DeployFile LocalName="JSExtension.exe" Configuration="Debug" Class="ProjectOutput"/>
<DeployFile LocalName="..\..\bin\JSRTTIExtension.exe" Configuration="Debug" Class="ProjectOutput"> <DeployFile LocalName="..\..\bin\JSRTTIExtension.exe" Configuration="Debug" Class="ProjectOutput">
<Platform Name="Win32"> <Platform Name="Win32">
<RemoteName>JSRTTIExtension.exe</RemoteName> <RemoteName>JSRTTIExtension.exe</RemoteName>
<Overwrite>true</Overwrite> <Overwrite>true</Overwrite>
</Platform> </Platform>
</DeployFile> </DeployFile>
<DeployFile LocalName="JSExtension.exe" Configuration="Debug" Class="ProjectOutput"/>
<DeployClass Name="AdditionalDebugSymbols"> <DeployClass Name="AdditionalDebugSymbols">
<Platform Name="iOSSimulator"> <Platform Name="iOSSimulator">
<Operation>1</Operation> <Operation>1</Operation>

View File

@ -38,7 +38,7 @@ object JSRTTIExtensionFrm: TJSRTTIExtensionFrm
Margins.Right = 5 Margins.Right = 5
Align = alClient Align = alClient
TabOrder = 0 TabOrder = 0
Text = 'http://www.google.com' Text = 'https://www.briskbard.com/forum/'
ExplicitHeight = 21 ExplicitHeight = 21
end end
object GoBtn: TButton object GoBtn: TButton

View File

@ -127,23 +127,29 @@ implementation
uses uses
uSimpleTextViewer, uCEFv8Handler, uTestExtension, uCEFMiscFunctions; uSimpleTextViewer, uCEFv8Handler, uTestExtension, uCEFMiscFunctions;
// The CEF3 document describing extensions is here :
// https://bitbucket.org/chromiumembedded/cef/wiki/JavaScriptIntegration.md
// This demo has a TTestExtension class that is registered in the // Please, read the code comments in the JSExtension demo (uJSExtension.pas) before using this demo!
// GlobalCEFApp.OnWebKitInitialized event when the application is initializing.
// This demo is almost identical to JSExtension but it uses a slightly easier
// way to register JavaScript extensions inherited from the DCEF3 project.
// Instead of creating a custom class inherited from TCefv8HandlerOwn and calling the
// CefRegisterExtension function, this demo uses the TCefRTTIExtension.Register
// class procedure to register the TTestExtension class, which is a custom Delphi
// class with 2 class procedures.
// TCefRTTIExtension uses the RTTI from the TTestExtension class to generate the
// JS code and the ICefv8Handler parameters needed by CefRegisterExtension.
// You still need to call TCefRTTIExtension.Register in the GlobalCEFApp.OnWebKitInitialized event
// and use process messages to send information between processes.
// TTestExtension can send information back to the browser with a process message. // TTestExtension can send information back to the browser with a process message.
// The TTestExtension.mouseover function do this by calling // The TTestExtension.mouseover function do this by calling
// TCefv8ContextRef.Current.Browser.MainFrame.SendProcessMessage(PID_BROWSER, msg); // TCefv8ContextRef.Current.Browser.MainFrame.SendProcessMessage(PID_BROWSER, msg);
// TCefv8ContextRef.Current returns the v8 context for the frame that is currently executing JS,
// TCefv8ContextRef.Current.Browser.MainFrame.SendProcessMessage should send a message to the right browser even
// if you have created several browsers in one app.
// That message is received in the TChromium.OnProcessMessageReceived event. // That message is received in the TChromium.OnProcessMessageReceived event.
// Even if you create several TChromium objects you should have no problem because each of them will have its own
// TChromium.OnProcessMessageReceived event to receive the messages from the extension.
// Destruction steps // Destruction steps
// ================= // =================
@ -205,6 +211,8 @@ procedure TJSRTTIExtensionFrm.Chromium1ContextMenuCommand(Sender: TObject;
const browser: ICefBrowser; const frame: ICefFrame; const browser: ICefBrowser; const frame: ICefFrame;
const params: ICefContextMenuParams; commandId: Integer; const params: ICefContextMenuParams; commandId: Integer;
eventFlags: Cardinal; out Result: Boolean); eventFlags: Cardinal; out Result: Boolean);
const
ELEMENT_ID = 'keywords'; // ID attribute in the search box at https://www.briskbard.com/forum/
begin begin
Result := False; Result := False;
@ -238,12 +246,12 @@ begin
// Delphi receives the the information in the Chromium1ProcessMessageReceived procedure and shows it in the status bar. // Delphi receives the the information in the Chromium1ProcessMessageReceived procedure and shows it in the status bar.
if (browser <> nil) and (browser.MainFrame <> nil) then if (browser <> nil) and (browser.MainFrame <> nil) then
browser.MainFrame.ExecuteJavaScript( browser.MainFrame.ExecuteJavaScript(
'var targetNode = document.getElementById(' + quotedstr('lst-ib') + ');' + // 'lst-ib' is the ID attribute in the search box at google.com 'var targetNode = document.getElementById(' + quotedstr(ELEMENT_ID) + ');' +
'var config = { attributes: true, childList: false, subtree: false };'+ 'var config = { attributes: true, childList: false, subtree: false };'+
'var callback = function(mutationsList, observer) {' + 'var callback = function(mutationsList, observer) {' +
' for(var mutation of mutationsList) {' + ' for(var mutation of mutationsList) {' +
' if (mutation.type == ' + quotedstr('attributes') + ') {' + ' if (mutation.type == ' + quotedstr('attributes') + ') {' +
' myextension.sendresulttobrowser(document.getElementById(' + quotedstr('lst-ib') + ').value, ' + quotedstr(MUTATIONOBSERVER_MESSAGE_NAME) + ');' + ' myextension.sendresulttobrowser(document.getElementById(' + quotedstr(ELEMENT_ID) + ').value, ' + quotedstr(MUTATIONOBSERVER_MESSAGE_NAME) + ');' +
' }' + ' }' +
' }' + ' }' +
'};' + '};' +
@ -294,6 +302,8 @@ procedure TJSRTTIExtensionFrm.FormShow(Sender: TObject);
begin begin
StatusBar1.Panels[0].Text := 'Initializing browser. Please wait...'; StatusBar1.Panels[0].Text := 'Initializing browser. Please wait...';
Chromium1.DefaultURL := Edit1.Text;
// GlobalCEFApp.GlobalContextInitialized has to be TRUE before creating any browser // GlobalCEFApp.GlobalContextInitialized has to be TRUE before creating any browser
// If it's not initialized yet, we use a simple timer to create the browser later. // If it's not initialized yet, we use a simple timer to create the browser later.
if not(Chromium1.CreateBrowser(CEFWindowParent1, '')) then Timer1.Enabled := True; if not(Chromium1.CreateBrowser(CEFWindowParent1, '')) then Timer1.Enabled := True;
@ -332,7 +342,6 @@ begin
StatusBar1.Panels[0].Text := ''; StatusBar1.Panels[0].Text := '';
CEFWindowParent1.UpdateSize; CEFWindowParent1.UpdateSize;
NavControlPnl.Enabled := True; NavControlPnl.Enabled := True;
GoBtn.Click;
end; end;
procedure TJSRTTIExtensionFrm.Chromium1BeforeClose( procedure TJSRTTIExtensionFrm.Chromium1BeforeClose(

View File

@ -22,8 +22,8 @@
<ResourceBaseClass Value="Form"/> <ResourceBaseClass Value="Form"/>
<IsVisibleTab Value="True"/> <IsVisibleTab Value="True"/>
<EditorIndex Value="1"/> <EditorIndex Value="1"/>
<TopLine Value="220"/> <TopLine Value="173"/>
<CursorPos X="3" Y="222"/> <CursorPos X="17" Y="207"/>
<UsageCount Value="20"/> <UsageCount Value="20"/>
<Loaded Value="True"/> <Loaded Value="True"/>
<LoadedDesigner Value="True"/> <LoadedDesigner Value="True"/>
@ -50,7 +50,7 @@
<DefaultSyntaxHighlighter Value="Delphi"/> <DefaultSyntaxHighlighter Value="Delphi"/>
</Unit3> </Unit3>
</Units> </Units>
<JumpHistory Count="9" HistoryIndex="8"> <JumpHistory Count="22" HistoryIndex="21">
<Position1> <Position1>
<Filename Value="uJSExtension.pas"/> <Filename Value="uJSExtension.pas"/>
</Position1> </Position1>
@ -86,6 +86,58 @@
<Filename Value="uJSExtension.pas"/> <Filename Value="uJSExtension.pas"/>
<Caret Line="126" TopLine="111"/> <Caret Line="126" TopLine="111"/>
</Position9> </Position9>
<Position10>
<Filename Value="uJSExtension.pas"/>
<Caret Line="136" Column="39" TopLine="127"/>
</Position10>
<Position11>
<Filename Value="uJSExtension.pas"/>
<Caret Line="144" Column="114" TopLine="127"/>
</Position11>
<Position12>
<Filename Value="uJSExtension.pas"/>
<Caret Line="150" Column="74" TopLine="127"/>
</Position12>
<Position13>
<Filename Value="uJSExtension.pas"/>
<Caret Line="199" Column="41" TopLine="173"/>
</Position13>
<Position14>
<Filename Value="uJSExtension.pas"/>
<Caret Line="201" Column="92" TopLine="173"/>
</Position14>
<Position15>
<Filename Value="uJSExtension.pas"/>
<Caret Line="205" Column="77" TopLine="173"/>
</Position15>
<Position16>
<Filename Value="uJSExtension.pas"/>
<Caret Line="207" Column="18" TopLine="173"/>
</Position16>
<Position17>
<Filename Value="uJSExtension.pas"/>
<Caret Line="31" Column="76"/>
</Position17>
<Position18>
<Filename Value="uJSExtension.pas"/>
<Caret Line="149" Column="96" TopLine="108"/>
</Position18>
<Position19>
<Filename Value="uJSExtension.pas"/>
<Caret Line="150" Column="73" TopLine="127"/>
</Position19>
<Position20>
<Filename Value="uJSExtension.pas"/>
<Caret Line="199" Column="40" TopLine="173"/>
</Position20>
<Position21>
<Filename Value="uJSExtension.pas"/>
<Caret Line="201" Column="91" TopLine="173"/>
</Position21>
<Position22>
<Filename Value="uJSExtension.pas"/>
<Caret Line="205" Column="75" TopLine="173"/>
</Position22>
</JumpHistory> </JumpHistory>
<RunParams> <RunParams>
<FormatVersion Value="2"/> <FormatVersion Value="2"/>

View File

@ -14,7 +14,7 @@ object JSExtensionFrm: TJSExtensionFrm
OnCreate = FormCreate OnCreate = FormCreate
OnShow = FormShow OnShow = FormShow
Position = poScreenCenter Position = poScreenCenter
LCLVersion = '2.0.2.0' LCLVersion = '2.0.4.0'
object NavControlPnl: TPanel object NavControlPnl: TPanel
Left = 0 Left = 0
Height = 21 Height = 21

View File

@ -132,53 +132,146 @@ implementation
uses uses
uSimpleTextViewer, uCEFMiscFunctions, uTestExtensionHandler; uSimpleTextViewer, uCEFMiscFunctions, uTestExtensionHandler;
// To test this demo follow these steps : // 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/design-documents/multi-process-architecture
// 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 Pascal.
// The DOM and JavaScript live in the RENDERER PROCESS, while the Pascal 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
// -------------- 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/cef/wiki/JavaScriptIntegration.md
// One of the most interesting JS features available in CEF are the JavaScript extensions because they
// can be used to execute custom Pascal code from JavaScript.
// If you put all you know so far together you can get any result or information in Pascal 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 Pascal code. This Pascal code is also executed in
// the RENDERER PROCESS.
// 3. The Pascal 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/projects/(default)/CefV8Handler.html
// In order to use that extension, you must register 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/cef/wiki/JavaScriptIntegration.md#markdown-header-functions-and-extensions
// https://bitbucket.org/chromiumembedded/cef/src/b6b033a52bb3f7059d169a4c8389966c8fe2531b/include/capi/cef_v8_capi.h#lines-924
// TESTING THIS DEMO :
// ===================
// 1. Run the demo and wait until google.com is loaded // 1. Run the demo and wait until google.com is loaded
// 2. Right-click and select the "Set the mouseover event" menu option. // 2. Right-click and select the "Set the mouseover event" menu option.
// 3. Move the mouse pointer over the web page and see the HTML elements in the status bar. // 3. Move the mouse pointer over the web page and see the HTML elements in the status bar.
// The CEF3 document describing extensions is here : // When you select the "Set the mouseover event" menu option, the
// https://bitbucket.org/chromiumembedded/cef/wiki/JavaScriptIntegration.md
// The Chromium project document describing Chromium's architecture is here :
// http://www.chromium.org/developers/design-documents/multi-process-architecture
// This demo has a JavaScript extension class that is registered in the
// GlobalCEFApp.OnWebKitInitialized event when the application is initializing.
// The extension in this demo is called "myextension" and it has 2 functions called
// "mouseover" and "sendresulttobrowser".
// When the JavaScript code uses those functions it executes the TTestExtensionHandler.Execute
// function in uTestExtensionHandler.pas.
// When you run this demo and you select the "Set the mouseover event" menu option, the
// TChromium.OnContextMenuCommand event is triggered and it adds an event listener to the // TChromium.OnContextMenuCommand event is triggered and it adds an event listener to the
// document's body. That listener calls one of the functions available in the registered // document's body. That listener calls one of the functions available in the registered
// extension called "myextension.mouseover". // extension called "myextension.mouseover".
// The TTestExtensionHandler.Execute function is executed in the renderer process and it // The TTestExtensionHandler.Execute function in the extension is executed and it
// can use the TCefv8ContextRef.Current.Browser.MainFrame.SendProcessMessage(PID_BROWSER, msg) function // uses TCefv8ContextRef.Current.Browser.MainFrame.SendProcessMessage(PID_BROWSER, msg)
// to send a message with the results to the browser process. // to send a process message with the results to the browser process.
// TCefv8ContextRef.Current returns the v8 context for the frame that is currently // That message is received in the TChromium.OnProcessMessageReceived event and it shows
// executing JavaScript, TCefv8ContextRef.Current.Browser.MainFrame.SendProcessMessage sends a message // the information in the status bar.
// to the right browser even if you have created several browsers in one app.
// That message is received in the TChromium.OnProcessMessageReceived event.
// Even if you create several TChromium objects you should have no problem because each of
// them will have its own TChromium.OnProcessMessageReceived event to receive the messages
// from the extension.
// TChromium.OnProcessMessageReceived receives that message and shows the information in
// the status bar.
// If you have to debug the code executed by the extension you will need to use the // If you have to debug the code executed by the extension you will need to use the
// debugging methods described in // debugging methods described in
// https://www.briskbard.com/index.php?lang=en&pageid=cef // https://www.briskbard.com/index.php?lang=en&pageid=cef
// Destruction steps
// DESTRUCTION STEPS
// ================= // =================
// 1. FormCloseQuery sets CanClose to FALSE calls TChromium.CloseBrowser which triggers // 1. FormCloseQuery sets CanClose to FALSE calls TChromium.CloseBrowser which triggers
// the TChromium.OnClose event. // the TChromium.OnClose event.

Binary file not shown.

View File

@ -21,7 +21,7 @@
</CompilerOptions> </CompilerOptions>
<Description Value="CEF4Delphi is an open source project created by Salvador Díaz Fau to embed Chromium-based browsers in applications made with Delphi or Lazarus/FPC."/> <Description Value="CEF4Delphi is an open source project created by Salvador Díaz Fau to embed Chromium-based browsers in applications made with Delphi or Lazarus/FPC."/>
<License Value="MPL 1.1"/> <License Value="MPL 1.1"/>
<Version Major="76" Minor="1" Release="11"/> <Version Major="76" Minor="1" Release="13"/>
<Files Count="143"> <Files Count="143">
<Item1> <Item1>
<Filename Value="..\source\uCEFAccessibilityHandler.pas"/> <Filename Value="..\source\uCEFAccessibilityHandler.pas"/>

View File

@ -62,7 +62,7 @@ uses
const const
CEF_SUPPORTED_VERSION_MAJOR = 76; CEF_SUPPORTED_VERSION_MAJOR = 76;
CEF_SUPPORTED_VERSION_MINOR = 1; CEF_SUPPORTED_VERSION_MINOR = 1;
CEF_SUPPORTED_VERSION_RELEASE = 11; CEF_SUPPORTED_VERSION_RELEASE = 13;
CEF_SUPPORTED_VERSION_BUILD = 0; CEF_SUPPORTED_VERSION_BUILD = 0;
CEF_CHROMEELF_VERSION_MAJOR = 76; CEF_CHROMEELF_VERSION_MAJOR = 76;

View File

@ -2,9 +2,9 @@
"UpdateLazPackages" : [ "UpdateLazPackages" : [
{ {
"ForceNotify" : true, "ForceNotify" : true,
"InternalVersion" : 24, "InternalVersion" : 26,
"Name" : "cef4delphi_lazarus.lpk", "Name" : "cef4delphi_lazarus.lpk",
"Version" : "76.1.11.0" "Version" : "76.1.13.0"
} }
], ],
"UpdatePackageData" : { "UpdatePackageData" : {