1
0
mirror of https://github.com/salvadordf/CEF4Delphi.git synced 2025-01-23 10:24:51 +02:00

Added a "Show DevTools" context menu option to the DOMVisitor demo

- Updated the DOMVisitor demo for Lazarus.
- Replaced some local variable types from string to ustring to fix some issues in Delpi XE2.
This commit is contained in:
Salvador Díaz Fau 2020-08-22 12:29:11 +02:00
parent 3c1dae426c
commit e36cd5e8c7
7 changed files with 707 additions and 121 deletions

View File

@ -1,7 +1,7 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{3B58D3C2-1F7F-4146-A307-5F778CD7C586}</ProjectGuid>
<ProjectVersion>18.8</ProjectVersion>
<ProjectVersion>19.0</ProjectVersion>
<FrameworkType>VCL</FrameworkType>
<MainSource>DOMVisitor.dpr</MainSource>
<Base>True</Base>
@ -686,6 +686,16 @@
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch2x">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch768">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
@ -708,6 +718,16 @@
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_LaunchDark2x">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch1125">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
@ -807,6 +827,16 @@
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch2x">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch320">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
@ -818,6 +848,16 @@
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch3x">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch640">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
@ -862,6 +902,26 @@
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_LaunchDark2x">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_LaunchDark3x">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectAndroidManifest">
<Platform Name="Android">
<Operation>1</Operation>
@ -909,6 +969,16 @@
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSLaunchScreen">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen</RemoteDir>
<Operation>64</Operation>
</Platform>
<Platform Name="iOSSimulator">
<RemoteDir>..\$(PROJECTNAME).launchscreen</RemoteDir>
<Operation>64</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSResource">
<Platform Name="iOSDevice32">
<Operation>1</Operation>

View File

@ -52,7 +52,7 @@ uses
Controls, Forms, Dialogs, StdCtrls, ExtCtrls, Types, ComCtrls, ClipBrd,
{$ENDIF}
uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFApplication, uCEFTypes,
uCEFConstants, uCEFWinControl, uCEFSentinel, uCEFChromiumCore;
uCEFConstants, uCEFWinControl, uCEFChromiumCore, uCEFChromiumEvents;
const
MINIBROWSER_VISITDOM_PARTIAL = WM_APP + $101;
@ -71,6 +71,7 @@ const
MINIBROWSER_CONTEXTMENU_VISITDOM_JS = MENU_ID_USER_FIRST + 5;
MINIBROWSER_CONTEXTMENU_SETINPUTVALUE_JS = MENU_ID_USER_FIRST + 6;
MINIBROWSER_CONTEXTMENU_SETINPUTVALUE_DT = MENU_ID_USER_FIRST + 7;
MINIBROWSER_CONTEXTMENU_SHOWDEVTOOLS = MENU_ID_USER_FIRST + 8;
DOMVISITOR_MSGNAME_PARTIAL = 'domvisitorpartial';
DOMVISITOR_MSGNAME_FULL = 'domvisitorfull';
@ -273,7 +274,7 @@ end;
procedure SimpleNodeSearch(const aDocument: ICefDomDocument; const aFrame : ICefFrame);
var
TempNode : ICefDomNode;
TempJSCode, TempMessage : string;
TempJSCode, TempMessage : ustring;
begin
try
if (aDocument <> nil) then
@ -376,7 +377,7 @@ var
i : NativeUInt;
TempCount : NativeUInt;
TempArray : TCefFrameIdentifierArray;
TempString : string;
TempString : ustring;
TempMsg : ICefProcessMessage;
begin
TempCount := browser.FrameCount;
@ -494,6 +495,8 @@ begin
model.AddItem(MINIBROWSER_CONTEXTMENU_COPYFRAMEIDS_2, 'Copy frame IDs in the render process');
model.AddItem(MINIBROWSER_CONTEXTMENU_SETINPUTVALUE_JS, 'Set INPUT value using JavaScript');
model.AddItem(MINIBROWSER_CONTEXTMENU_SETINPUTVALUE_DT, 'Set INPUT value using DevTools methods');
model.AddSeparator;
model.AddItem(MINIBROWSER_CONTEXTMENU_SHOWDEVTOOLS, 'Show DevTools');
end;
procedure TDOMVisitorFrm.Chromium1BeforePopup(Sender: TObject;
@ -548,6 +551,8 @@ procedure TDOMVisitorFrm.Chromium1ContextMenuCommand(Sender: TObject;
const browser: ICefBrowser; const frame: ICefFrame;
const params: ICefContextMenuParams; commandId: Integer;
eventFlags: Cardinal; out Result: Boolean);
var
TempPoint : TPoint;
begin
Result := False;
@ -576,6 +581,13 @@ begin
FStatus := dvsGettingDocNodeID
else
FStatus := dvsIdle;
MINIBROWSER_CONTEXTMENU_SHOWDEVTOOLS :
begin
TempPoint.x := params.XCoord;
TempPoint.y := params.YCoord;
Chromium1.ShowDevTools(TempPoint, nil);
end;
end;
end;
@ -644,7 +656,7 @@ function TDOMVisitorFrm.HandleErrorRslt(const aResult: ICefValue) : boolean;
var
TempRsltDict : ICefDictionaryValue;
TempCode : integer;
TempMessage : string;
TempMessage : ustring;
begin
Result := False;

View File

@ -109,7 +109,6 @@
<VerInfo_Keys>CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName);FileDescription=$(MSBuildProjectName);ProductName=$(MSBuildProjectName)</VerInfo_Keys>
<DCC_IntegerOverflowCheck>true</DCC_IntegerOverflowCheck>
<DCC_RangeChecking>true</DCC_RangeChecking>
<AppDPIAwarenessMode>PerMonitor</AppDPIAwarenessMode>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1_Win64)'!=''">
<AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
@ -170,10 +169,10 @@
<Source Name="MainSource">MiniBrowser.dpr</Source>
</Source>
<Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\dclIPIndyImpl260.bpl">IP Abstraction Indy Implementation Design Time</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\DataExplorerDBXPluginEnt260.bpl">DBExpress Enterprise Data Explorer Integration</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\dcloffice2k260.bpl">Microsoft Office 2000 Sample Automation Server Wrapper Components</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\dclofficexp260.bpl">Microsoft Office XP Sample Automation Server Wrapper Components</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\dclIPIndyImpl270.bpl">IP Abstraction Indy Implementation Design Time</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\dclDataSnapNativeServer270.bpl">Embarcadero DBExpress DataSnap Native Server Components</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\dcloffice2k270.bpl">Microsoft Office 2000 Sample Automation Server Wrapper Components</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\dclofficexp270.bpl">Microsoft Office XP Sample Automation Server Wrapper Components</Excluded_Packages>
</Excluded_Packages>
</Delphi.Personality>
<Deployment Version="3">

View File

@ -8,8 +8,8 @@
<Unit0>
<Filename Value="DOMVisitor.lpr"/>
<IsPartOfProject Value="True"/>
<TopLine Value="38"/>
<CursorPos X="13" Y="44"/>
<TopLine Value="41"/>
<CursorPos X="94" Y="53"/>
<UsageCount Value="20"/>
<Loaded Value="True"/>
<DefaultSyntaxHighlighter Value="Delphi"/>
@ -22,8 +22,8 @@
<ResourceBaseClass Value="Form"/>
<IsVisibleTab Value="True"/>
<EditorIndex Value="1"/>
<TopLine Value="311"/>
<CursorPos X="41" Y="330"/>
<TopLine Value="358"/>
<CursorPos X="65" Y="374"/>
<UsageCount Value="20"/>
<Loaded Value="True"/>
<LoadedDesigner Value="True"/>
@ -47,11 +47,10 @@
</Unit3>
<Unit4>
<Filename Value="..\..\..\source\uCEFDomVisitor.pas"/>
<EditorIndex Value="2"/>
<EditorIndex Value="-1"/>
<TopLine Value="66"/>
<CursorPos X="3" Y="73"/>
<UsageCount Value="10"/>
<Loaded Value="True"/>
</Unit4>
<Unit5>
<Filename Value="..\..\..\source\uCEFInterfaces.pas"/>
@ -64,122 +63,123 @@
<JumpHistory Count="30" HistoryIndex="29">
<Position1>
<Filename Value="uDOMVisitor.pas"/>
<Caret Line="261" Column="11" TopLine="243"/>
<Caret Line="338" Column="39" TopLine="331"/>
</Position1>
<Position2>
<Filename Value="uDOMVisitor.pas"/>
<Caret Line="305" Column="81" TopLine="287"/>
<Caret Line="252" Column="77" TopLine="231"/>
</Position2>
<Position3>
<Filename Value="uDOMVisitor.pas"/>
<Caret Line="305" Column="113" TopLine="287"/>
<Caret Line="260" Column="81" TopLine="260"/>
</Position3>
<Position4>
<Filename Value="uDOMVisitor.pas"/>
<Caret Line="311" Column="59" TopLine="287"/>
<Caret Line="260" Column="81" TopLine="260"/>
</Position4>
<Position5>
<Filename Value="uDOMVisitor.pas"/>
<Caret Line="261" Column="11" TopLine="109"/>
<Caret Line="256" Column="53" TopLine="236"/>
</Position5>
<Position6>
<Filename Value="uDOMVisitor.pas"/>
<Caret Line="305" Column="44" TopLine="287"/>
<Caret Line="276" Column="62" TopLine="263"/>
</Position6>
<Position7>
<Filename Value="uDOMVisitor.pas"/>
<Caret Line="305" Column="44" TopLine="287"/>
<Caret Line="291" Column="74" TopLine="281"/>
</Position7>
<Position8>
<Filename Value="uDOMVisitor.pas"/>
<Caret Line="483" TopLine="449"/>
<Caret Line="371" Column="55" TopLine="358"/>
</Position8>
<Position9>
<Filename Value="uDOMVisitor.pas"/>
<Caret Line="52" TopLine="33"/>
<Filename Value="DOMVisitor.lpr"/>
<Caret Line="44" Column="13" TopLine="38"/>
</Position9>
<Position10>
<Filename Value="uDOMVisitor.pas"/>
<Caret Line="305" TopLine="294"/>
</Position10>
<Position11>
<Filename Value="uDOMVisitor.pas"/>
<Caret Line="136" Column="8" TopLine="106"/>
<Caret Line="307" TopLine="296"/>
</Position11>
<Position12>
<Filename Value="uDOMVisitor.pas"/>
<Caret Line="305" Column="67" TopLine="289"/>
<Caret Line="163" Column="82" TopLine="151"/>
</Position12>
<Position13>
<Filename Value="uDOMVisitor.pas"/>
<Caret Line="378" Column="16" TopLine="364"/>
<Caret Line="162" Column="82" TopLine="150"/>
</Position13>
<Position14>
<Filename Value="uDOMVisitor.pas"/>
<Caret Line="121" Column="15" TopLine="111"/>
<Caret Line="161" Column="72" TopLine="146"/>
</Position14>
<Position15>
<Filename Value="uDOMVisitor.pas"/>
<Caret Line="100" Column="43" TopLine="79"/>
<Caret Line="434" TopLine="340"/>
</Position15>
<Position16>
<Filename Value="uDOMVisitor.pas"/>
<Caret Line="338" Column="39" TopLine="331"/>
<Caret Line="91" Column="68" TopLine="73"/>
</Position16>
<Position17>
<Filename Value="uDOMVisitor.pas"/>
<Caret Line="252" Column="77" TopLine="231"/>
<Caret Line="93" Column="32" TopLine="73"/>
</Position17>
<Position18>
<Filename Value="uDOMVisitor.pas"/>
<Caret Line="260" Column="81" TopLine="260"/>
<Caret Line="448" TopLine="424"/>
</Position18>
<Position19>
<Filename Value="uDOMVisitor.pas"/>
<Caret Line="260" Column="81" TopLine="260"/>
<Filename Value="DOMVisitor.lpr"/>
<Caret Line="53" Column="94" TopLine="41"/>
</Position19>
<Position20>
<Filename Value="uDOMVisitor.pas"/>
<Caret Line="256" Column="53" TopLine="236"/>
<Caret Line="81" Column="98" TopLine="77"/>
</Position20>
<Position21>
<Filename Value="uDOMVisitor.pas"/>
<Caret Line="276" Column="62" TopLine="263"/>
<Caret Line="518" Column="26" TopLine="503"/>
</Position21>
<Position22>
<Filename Value="uDOMVisitor.pas"/>
<Caret Line="291" Column="74" TopLine="281"/>
<Caret Line="525" Column="3" TopLine="521"/>
</Position22>
<Position23>
<Filename Value="uDOMVisitor.pas"/>
<Caret Line="371" Column="55" TopLine="358"/>
<Caret Line="688" Column="60" TopLine="665"/>
</Position23>
<Position24>
<Filename Value="DOMVisitor.lpr"/>
<Caret Line="44" Column="13" TopLine="38"/>
<Filename Value="uDOMVisitor.pas"/>
<Caret Line="53" Column="76" TopLine="40"/>
</Position24>
<Position25>
<Filename Value="uDOMVisitor.pas"/>
<Caret Line="305" TopLine="294"/>
<Caret Line="759" Column="41" TopLine="742"/>
</Position25>
<Position26>
<Filename Value="uDOMVisitor.pas"/>
<Caret Line="307" TopLine="296"/>
<Caret Line="101" Column="48" TopLine="91"/>
</Position26>
<Position27>
<Filename Value="uDOMVisitor.pas"/>
<Caret Line="163" Column="82" TopLine="151"/>
<Caret Line="775" Column="60" TopLine="756"/>
</Position27>
<Position28>
<Filename Value="uDOMVisitor.pas"/>
<Caret Line="162" Column="82" TopLine="150"/>
<Caret Line="110" Column="38" TopLine="96"/>
</Position28>
<Position29>
<Filename Value="uDOMVisitor.pas"/>
<Caret Line="161" Column="72" TopLine="146"/>
<Caret Line="518" Column="49" TopLine="509"/>
</Position29>
<Position30>
<Filename Value="uDOMVisitor.pas"/>
<Caret Line="434" TopLine="340"/>
<Caret Line="770" TopLine="93"/>
</Position30>
</JumpHistory>
<RunParams>

View File

@ -12,9 +12,10 @@ object DOMVisitorFrm: TDOMVisitorFrm
Font.Name = 'Tahoma'
OnCloseQuery = FormCloseQuery
OnCreate = FormCreate
OnDestroy = FormDestroy
OnShow = FormShow
Position = poScreenCenter
LCLVersion = '2.0.6.0'
LCLVersion = '2.0.10.0'
object CEFWindowParent1: TCEFWindowParent
Left = 0
Height = 539
@ -43,7 +44,7 @@ object DOMVisitorFrm: TDOMVisitorFrm
Width = 764
Align = alClient
TabOrder = 0
Text = 'https://www.google.com'
Text = 'https://www.briskbard.com/forum/'
end
object Panel1: TPanel
Left = 764
@ -90,18 +91,20 @@ object DOMVisitorFrm: TDOMVisitorFrm
OnProcessMessageReceived = Chromium1ProcessMessageReceived
OnBeforeContextMenu = Chromium1BeforeContextMenu
OnContextMenuCommand = Chromium1ContextMenuCommand
OnConsoleMessage = Chromium1ConsoleMessage
OnBeforePopup = Chromium1BeforePopup
OnAfterCreated = Chromium1AfterCreated
OnBeforeClose = Chromium1BeforeClose
OnClose = Chromium1Close
left = 16
top = 40
OnDevToolsMethodResult = Chromium1DevToolsMethodResult
Left = 16
Top = 40
end
object Timer1: TTimer
Enabled = False
Interval = 300
OnTimer = Timer1Timer
left = 16
top = 96
Left = 16
Top = 96
end
end

View File

@ -44,27 +44,42 @@ unit uDOMVisitor;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Menus,
Windows, Messages, SysUtils, Variants, Classes, Graphics, Menus, SyncObjs,
Controls, Forms, Dialogs, StdCtrls, ExtCtrls, Types, ComCtrls, ClipBrd,
uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFApplication, uCEFTypes, uCEFConstants,
uCEFWinControl, uCEFSentinel;
uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFApplication, uCEFTypes,
uCEFConstants, uCEFWinControl, uCEFChromiumCore, uCEFChromiumEvents;
const
MINIBROWSER_VISITDOM_PARTIAL = WM_APP + $101;
MINIBROWSER_VISITDOM_FULL = WM_APP + $102;
MINIBROWSER_COPYFRAMEIDS_1 = WM_APP + $103;
MINIBROWSER_COPYFRAMEIDS_2 = WM_APP + $104;
MINIBROWSER_SHOWMESSAGE = WM_APP + $105;
MINIBROWSER_SHOWSTATUSTEXT = WM_APP + $106;
MINIBROWSER_VISITDOM_JS = WM_APP + $107;
MINIBROWSER_SHOWERROR = WM_APP + $108;
MINIBROWSER_CONTEXTMENU_VISITDOM_PARTIAL = MENU_ID_USER_FIRST + 1;
MINIBROWSER_CONTEXTMENU_VISITDOM_FULL = MENU_ID_USER_FIRST + 2;
MINIBROWSER_CONTEXTMENU_COPYFRAMEIDS_1 = MENU_ID_USER_FIRST + 3;
MINIBROWSER_CONTEXTMENU_COPYFRAMEIDS_2 = MENU_ID_USER_FIRST + 4;
MINIBROWSER_CONTEXTMENU_VISITDOM_JS = MENU_ID_USER_FIRST + 5;
MINIBROWSER_CONTEXTMENU_SETINPUTVALUE_JS = MENU_ID_USER_FIRST + 6;
MINIBROWSER_CONTEXTMENU_SETINPUTVALUE_DT = MENU_ID_USER_FIRST + 7;
MINIBROWSER_CONTEXTMENU_SHOWDEVTOOLS = MENU_ID_USER_FIRST + 8;
DOMVISITOR_MSGNAME_PARTIAL = 'domvisitorpartial';
DOMVISITOR_MSGNAME_FULL = 'domvisitorfull';
RETRIEVEDOM_MSGNAME_PARTIAL = 'retrievedompartial';
RETRIEVEDOM_MSGNAME_FULL = 'retrievedomfull';
FRAMEIDS_MSGNAME = 'getframeids';
CONSOLE_MSG_PREAMBLE = 'DOMVISITOR';
type
NODE_ID = 'keywords';
type
TDTVisitStatus = (dvsIdle, dvsGettingDocNodeID, dvsQueryingSelector, dvsSettingAttributeValue);
{ TDOMVisitorFrm }
TDOMVisitorFrm = class(TForm)
CEFWindowParent1: TCEFWindowParent;
Chromium1: TChromium;
@ -75,54 +90,72 @@ type
Panel1: TPanel;
GoBtn: TButton;
VisitDOMBtn: TButton;
procedure CEFSentinel1Close(Sender: TObject);
procedure GoBtnClick(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure Chromium1AfterCreated(Sender: TObject;
const browser: ICefBrowser);
procedure Chromium1BeforeContextMenu(Sender: TObject;
const browser: ICefBrowser; const frame: ICefFrame;
const params: ICefContextMenuParams; const model: ICefMenuModel);
procedure Chromium1ContextMenuCommand(Sender: TObject;
const browser: ICefBrowser; const frame: ICefFrame;
const params: ICefContextMenuParams; commandId: Integer;
eventFlags: Cardinal; out Result: Boolean);
procedure Chromium1ProcessMessageReceived(Sender: TObject;
const browser: ICefBrowser; const frame: ICefFrame; sourceProcess: TCefProcessId;
const message: ICefProcessMessage; out Result: Boolean);
procedure Timer1Timer(Sender: TObject);
procedure VisitDOMBtnClick(Sender: TObject);
procedure Chromium1BeforePopup(Sender: TObject;
const browser: ICefBrowser; const frame: ICefFrame; const targetUrl,
targetFrameName: ustring;
targetDisposition: TCefWindowOpenDisposition; userGesture: Boolean;
const popupFeatures: TCefPopupFeatures; var windowInfo: TCefWindowInfo;
var client: ICefClient; var settings: TCefBrowserSettings;
var extra_info: ICefDictionaryValue;
var noJavascriptAccess: Boolean; var Result: Boolean);
procedure FormShow(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure Chromium1Close(Sender: TObject; const browser: ICefBrowser;
var aAction : TCefCloseBrowserAction);
procedure Chromium1BeforeClose(Sender: TObject;
const browser: ICefBrowser);
private
{ Private declarations }
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure FormDestroy(Sender: TObject);
procedure Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser);
procedure Chromium1BeforeContextMenu(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; const params: ICefContextMenuParams; const model: ICefMenuModel);
procedure Chromium1ContextMenuCommand(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; const params: ICefContextMenuParams; commandId: Integer; eventFlags: Cardinal; out Result: Boolean);
procedure Chromium1ProcessMessageReceived(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; sourceProcess: TCefProcessId; const message: ICefProcessMessage; out Result: Boolean);
procedure Chromium1BeforePopup(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; const targetUrl, targetFrameName: ustring; targetDisposition: TCefWindowOpenDisposition; userGesture: Boolean; const popupFeatures: TCefPopupFeatures; var windowInfo: TCefWindowInfo; var client: ICefClient; var settings: TCefBrowserSettings; var extra_info: ICefDictionaryValue; var noJavascriptAccess: Boolean; var Result: Boolean);
procedure Chromium1Close(Sender: TObject; const browser: ICefBrowser; var aAction : TCefCloseBrowserAction);
procedure Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser);
procedure Chromium1ConsoleMessage(Sender: TObject; const browser: ICefBrowser; level: TCefLogSeverity; const message, source: ustring; line: Integer; out Result: Boolean);
procedure Chromium1DevToolsMethodResult(Sender: TObject; const browser: ICefBrowser; message_id: integer; success: boolean; const result: ICefValue);
protected
// Variables to control when can we destroy the form safely
FCanClose : boolean; // Set to True in TChromium.OnBeforeClose
FClosing : boolean; // Set to True in the CloseQuery event.
// Critical section and fields to show information received in CEF events safely.
FCritSection : TCriticalSection;
FMsgContents : string;
FStatusText : string;
FStatus : TDTVisitStatus;
FErrorText : string;
function GetMsgContents : string;
function GetStatusText : string;
function GetErrorText : string;
procedure SetMsgContents(const aValue : string);
procedure SetStatusText(const aValue : string);
procedure SetErrorText(const aValue : string);
procedure BrowserCreatedMsg(var aMessage : TMessage); message CEF_AFTERCREATED;
procedure BrowserDestroyMsg(var aMessage : TMessage); message CEF_DESTROY;
procedure VisitDOMMsg(var aMessage : TMessage); message MINIBROWSER_VISITDOM_PARTIAL;
procedure VisitDOM2Msg(var aMessage : TMessage); message MINIBROWSER_VISITDOM_FULL;
procedure VisitDOM3Msg(var aMessage : TMessage); message MINIBROWSER_VISITDOM_JS;
procedure CopyFrameIDs1(var aMessage : TMessage); message MINIBROWSER_COPYFRAMEIDS_1;
procedure CopyFrameIDs2(var aMessage : TMessage); message MINIBROWSER_COPYFRAMEIDS_2;
procedure ShowMessageMsg(var aMessage : TMessage); message MINIBROWSER_SHOWMESSAGE;
procedure ShowStatusTextMsg(var aMessage : TMessage); message MINIBROWSER_SHOWSTATUSTEXT;
procedure ShowErrorMsg(var aMessage : TMessage); message MINIBROWSER_SHOWERROR;
procedure WMMove(var aMessage : TWMMove); message WM_MOVE;
procedure WMMoving(var aMessage : TMessage); message WM_MOVING;
procedure ShowStatusText(const aText : string);
public
{ Public declarations }
function QuerySelector(aNodeID : integer; const aSelector : string) : integer;
function SetAttributeValue(aNodeID : integer; const aName, aValue : string) : integer;
function HandleGetDocumentRslt(aSuccess : boolean; const aResult: ICefValue) : boolean;
function HandleQuerySelectorRslt(aSuccess : boolean; const aResult: ICefValue) : boolean;
function HandleSetAttributeValueRslt(aSuccess : boolean; const aResult: ICefValue) : boolean;
function HandleErrorRslt(const aResult: ICefValue) : boolean;
property MsgContents : string read GetMsgContents write SetMsgContents;
property StatusText : string read GetStatusText write SetStatusText;
property ErrorText : string read GetErrorText write SetErrorText;
end;
var
@ -135,30 +168,77 @@ implementation
{$R *.lfm}
uses
uCEFProcessMessage, uCEFMiscFunctions, uCEFSchemeRegistrar, uCEFRenderProcessHandler,
uCEFv8Handler, uCEFDomVisitor, uCEFDomNode, uCEFTask;
uCEFProcessMessage, uCEFMiscFunctions, uCEFSchemeRegistrar,
uCEFRenderProcessHandler, uCEFv8Handler, uCEFDomVisitor, uCEFDomNode,
uCEFTask, uCEFDictionaryValue, uCEFJson;
// This demo sends messages from the browser process to the render process,
// and from the render process to the browser process.
// To send a message from the browser process you must use the TChromium.SendProcessMessage
// procedure with a PID_RENDERER parameter. The render process receives those messages in
// the GlobalCEFApp.OnProcessMessageReceived event.
// To send a message from the browser process you must use the
// TChromium.SendProcessMessage procedure with a PID_RENDERER parameter. The
// render process receives those messages in the
// GlobalCEFApp.OnProcessMessageReceived event.
// To send messages from the render process you must use the frame.SendProcessMessage
// procedure with a PID_BROWSER parameter. The browser process receives those messages in
// the TChromium.OnProcessMessageReceived event.
// To send messages from the render process you must use the
// frame.SendProcessMessage procedure with a PID_BROWSER parameter. The browser
// process receives those messages in the TChromium.OnProcessMessageReceived
// event.
// message.name is used to identify different messages sent with SendProcessMessage.
// message.name is used to identify different messages sent with
// SendProcessMessage.
// The OnProcessMessageReceived event can recognize any number of messages identifying them
// by message.name
// The OnProcessMessageReceived event can recognize any number of messages
// identifying them by message.name
// The CEF API is not as powerful as JavaScript to visit the DOM. Consider using
// TChromium.ExecuteJavaScript to execute custom JS code in case you need more
// powerful features.
// Read the code comments in the JSExtension demo for more information about the
// Chromium processes and how to send messages between them :
// https://github.com/salvadordf/CEF4Delphi/blob/master/demos/Delphi_VCL/JavaScript/JSExtension/uJSExtension.pas
// This demo also uses de "console trick" to send information from the render
// process to the browser process.
// This method for sending text messages is limited to around 10000 characters
// but it's much easier to implement than using a JavaScript extension.
// It cosist of using the JavaScript command "console.log" with a known text
// preamble. The browser process receives the console message in the
// TChromium.OnConsoleMessage event and we identify the right message thanks to
// the preamble in the message.
// This demo also uses DevTool methods to change the "value" attribute of an
// INPUT HTML element. Each method is called using the
// TChromium.ExecuteDevToolsMethod function and the results are received in the
// TChromium.OnDevToolsMethodResult event.
// To test this feature right click on the web page and select the "Set INPUT
// value using DevTools methods" option.
// That menu option will execute the "DOM.getDocument" method to get the NodeId
// of the document node and it will trigger the TChromium.OnDevToolsMethodResult event.
// In that event we use the NodeId of the document to call the "DOM.querySelector" method
// with the "#keywords" selector, which is the ID atttribute of the INPUT element we need.
// The TChromium.OnDevToolsMethodResult event is triggered once again and now we have the
// NodeId of the INPUT element. Now we can call the "DOM.setAttributeValue" method to
// update the "value" attribute in the INPUT element.
// Read these documents for more details about the DevTools methods :
// General information -> https://chromedevtools.github.io/devtools-protocol/
// "DOM.getDocument" method -> https://chromedevtools.github.io/devtools-protocol/tot/DOM/#method-getDocument
// "DOM.querySelector" method -> https://chromedevtools.github.io/devtools-protocol/tot/DOM/#method-querySelector
// "DOM.setAttributeValue" method -> https://chromedevtools.github.io/devtools-protocol/tot/DOM/#method-setAttributeValue
// Destruction steps
// =================
// 1. FormCloseQuery sets CanClose to FALSE calls TChromium.CloseBrowser which triggers the TChromium.OnClose event.
// 2. TChromium.OnClose sends a CEFBROWSER_DESTROY message to destroy CEFWindowParent1 in the main thread, which triggers the TChromium.OnBeforeClose event.
// 3. TChromium.OnBeforeClose sets FCanClose := True and sends WM_CLOSE to the form.
// 1. FormCloseQuery sets CanClose to FALSE calls TChromium.CloseBrowser which
// triggers the TChromium.OnClose event.
// 2. TChromium.OnClose sends a CEFBROWSER_DESTROY message to destroy
// CEFWindowParent1 in the main thread, which triggers the
// TChromium.OnBeforeClose event.
// 3. TChromium.OnBeforeClose sets FCanClose := True and sends WM_CLOSE to the
// form.
procedure SimpleDOMIteration(const aDocument: ICefDomDocument);
var
@ -186,11 +266,10 @@ begin
end;
end;
procedure SimpleNodeSearch(const aDocument: ICefDomDocument);
const
NODE_ID = 'lst-ib'; // input box node found in google.com homepage
procedure SimpleNodeSearch(const aDocument: ICefDomDocument; const aFrame : ICefFrame);
var
TempNode : ICefDomNode;
TempJSCode, TempMessage : ustring;
begin
try
if (aDocument <> nil) then
@ -199,8 +278,27 @@ begin
if (TempNode <> nil) then
begin
CefLog('CEF4Delphi', 1, CEF_LOG_SEVERITY_ERROR, NODE_ID + ' element name : ' + TempNode.Name);
CefLog('CEF4Delphi', 1, CEF_LOG_SEVERITY_ERROR, NODE_ID + ' element value : ' + TempNode.GetValue);
// Here we send the name and value of the element with the "console trick".
// The name and value contents are included in TempMessage and the we
// execute "console.log" in JavaScript to send TempMessage with a
// known preamble that will be used to identify the message in the
// TChromium.OnConsoleMessage event.
// NOTE : In case you try to read or write node values using the CEF API
// you should know that ICefDomNode.GetValue and ICefDomNode.SetValue
// only work in text nodes. ICefDomNode.GetElementAttribute returns
// the attribute value specified in the HTML and not the current value.
// It's recommended that you use JavaScript or DevTools methods if
// you need to get or set the value of HTML elements.
// For example, if you want to use the "console trick" and you want
// to get the value of the search box in our forum you would have to
// execute this JavaScript code :
// console.log("DOMVISITOR" + document.getElementById("keywords").value);
TempMessage := 'name:' + TempNode.Name;
TempJSCode := 'console.log("' + CONSOLE_MSG_PREAMBLE + TempMessage + '");';
aFrame.ExecuteJavaScript(TempJSCode, 'about:blank', 0);
end;
TempNode := aDocument.GetFocusedNode;
@ -235,7 +333,7 @@ begin
SimpleDOMIteration(document);
// Simple DOM searches
SimpleNodeSearch(document);
SimpleNodeSearch(document, frame);
// Sending back some custom results to the browser process
// Notice that the DOMVISITOR_MSGNAME_PARTIAL message name needs to be recognized in
@ -269,6 +367,39 @@ begin
end;
end;
procedure DOMVisitor_GetFrameIDs(const browser: ICefBrowser; const frame : ICefFrame);
var
i : NativeUInt;
TempCount : NativeUInt;
TempArray : TCefFrameIdentifierArray;
TempString : ustring;
TempMsg : ICefProcessMessage;
begin
TempCount := browser.FrameCount;
if browser.GetFrameIdentifiers(TempCount, TempArray) then
begin
TempString := '';
i := 0;
while (i < TempCount) do
begin
TempString := TempString + inttostr(TempArray[i]) + CRLF;
inc(i);
end;
try
TempMsg := TCefProcessMessageRef.New(FRAMEIDS_MSGNAME);
TempMsg.ArgumentList.SetString(0, TempString);
if (frame <> nil) and frame.IsValid then
frame.SendProcessMessage(PID_BROWSER, TempMsg);
finally
TempMsg := nil;
end;
end;
end;
procedure GlobalCEFApp_OnProcessMessageReceived(const browser : ICefBrowser;
const frame : ICefFrame;
sourceProcess : TCefProcessId;
@ -301,7 +432,13 @@ begin
end;
aHandled := True;
end;
end
else
if (message.name = FRAMEIDS_MSGNAME) then
begin
DOMVisitor_GetFrameIDs(browser, frame);
aHandled := True;
end;
end;
end;
@ -309,13 +446,25 @@ procedure CreateGlobalCEFApp;
begin
GlobalCEFApp := TCefApplication.Create;
GlobalCEFApp.RemoteDebuggingPort := 9000;
GlobalCEFApp.OnProcessMessageReceived := GlobalCEFApp_OnProcessMessageReceived;
GlobalCEFApp.OnProcessMessageReceived := GlobalCEFApp_OnProcessMessageReceived;
// Enabling the debug log file for then DOM visitor demo.
// This adds lots of warnings to the console, specially if you run this inside VirtualBox.
// Remove it if you don't want to use the DOM visitor
GlobalCEFApp.LogFile := 'debug.log';
GlobalCEFApp.LogSeverity := LOGSEVERITY_INFO;
// Delphi can only debug one process and it debugs the browser process by
// default. If you need to debug code executed in the render process you will
// need to use any of the methods described here :
// https://www.briskbard.com/index.php?lang=en&pageid=cef#debugging
// Using the "Single process" mode is one of the ways to debug all the code
// because everything is executed in the browser process and Delphi won't have
// any problems. However, The "Single process" mode is unsupported by CEF and
// it causes unexpected issues. You should *ONLY* use it for debugging
// purposses.
//GlobalCEFApp.SingleProcess := True;
end;
procedure TDOMVisitorFrm.Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser);
@ -336,6 +485,13 @@ procedure TDOMVisitorFrm.Chromium1BeforeContextMenu(Sender: TObject;
begin
model.AddItem(MINIBROWSER_CONTEXTMENU_VISITDOM_PARTIAL, 'Visit DOM in CEF (only Title)');
model.AddItem(MINIBROWSER_CONTEXTMENU_VISITDOM_FULL, 'Visit DOM in CEF (BODY HTML)');
model.AddItem(MINIBROWSER_CONTEXTMENU_VISITDOM_JS, 'Visit DOM using JavaScript');
model.AddItem(MINIBROWSER_CONTEXTMENU_COPYFRAMEIDS_1, 'Copy frame IDs in the browser process');
model.AddItem(MINIBROWSER_CONTEXTMENU_COPYFRAMEIDS_2, 'Copy frame IDs in the render process');
model.AddItem(MINIBROWSER_CONTEXTMENU_SETINPUTVALUE_JS, 'Set INPUT value using JavaScript');
model.AddItem(MINIBROWSER_CONTEXTMENU_SETINPUTVALUE_DT, 'Set INPUT value using DevTools methods');
model.AddSeparator;
model.AddItem(MINIBROWSER_CONTEXTMENU_SHOWDEVTOOLS, 'Show DevTools');
end;
procedure TDOMVisitorFrm.Chromium1BeforePopup(Sender: TObject;
@ -359,10 +515,39 @@ begin
aAction := cbaDelay;
end;
procedure TDOMVisitorFrm.Chromium1ConsoleMessage(Sender: TObject;
const browser: ICefBrowser; level: Cardinal; const message, source: ustring;
line: Integer; out Result: Boolean);
begin
// In this event we receive the message with the name and value of a DOM node
// from the render process.
// This event may receive many other messages but we identify our message
// thanks to the preamble.
// The we set MsgContents with the rest of the message and send a
// MINIBROWSER_SHOWMESSAGE message to show MsgContents in the main thread safely.
// This and many other TChromium events are executed in a CEF thread. The VCL
// should be used only in the main thread and we use a message and a field
// protected by a synchronization object to call showmessage safely.
if (length(message) > 0) and
(copy(message, 1, length(CONSOLE_MSG_PREAMBLE)) = CONSOLE_MSG_PREAMBLE) then
begin
MsgContents := copy(message, succ(length(CONSOLE_MSG_PREAMBLE)), length(message));
if (length(MsgContents) = 0) then
MsgContents := 'There was an error reading the search box information'
else
MsgContents := 'Search box information: ' + quotedstr(MsgContents);
PostMessage(Handle, MINIBROWSER_SHOWMESSAGE, 0, 0);
end;
end;
procedure TDOMVisitorFrm.Chromium1ContextMenuCommand(Sender: TObject;
const browser: ICefBrowser; const frame: ICefFrame;
const params: ICefContextMenuParams; commandId: Integer;
eventFlags: Cardinal; out Result: Boolean);
var
TempPoint : TPoint;
begin
Result := False;
@ -372,9 +557,143 @@ begin
MINIBROWSER_CONTEXTMENU_VISITDOM_FULL :
PostMessage(Handle, MINIBROWSER_VISITDOM_FULL, 0, 0);
MINIBROWSER_CONTEXTMENU_VISITDOM_JS :
PostMessage(Handle, MINIBROWSER_VISITDOM_JS, 0, 0);
MINIBROWSER_CONTEXTMENU_COPYFRAMEIDS_1 :
PostMessage(Handle, MINIBROWSER_COPYFRAMEIDS_1, 0, 0);
MINIBROWSER_CONTEXTMENU_COPYFRAMEIDS_2 :
PostMessage(Handle, MINIBROWSER_COPYFRAMEIDS_2, 0, 0);
MINIBROWSER_CONTEXTMENU_SETINPUTVALUE_JS :
frame.ExecuteJavaScript('document.getElementById("' + NODE_ID + '").value = "qwerty";', 'about:blank', 0);
MINIBROWSER_CONTEXTMENU_SETINPUTVALUE_DT :
// https://chromedevtools.github.io/devtools-protocol/tot/DOM/#method-getDocument
if (Chromium1.ExecuteDevToolsMethod(0, 'DOM.getDocument', nil) <> 0) then
FStatus := dvsGettingDocNodeID
else
FStatus := dvsIdle;
MINIBROWSER_CONTEXTMENU_SHOWDEVTOOLS :
begin
TempPoint.x := params.XCoord;
TempPoint.y := params.YCoord;
Chromium1.ShowDevTools(TempPoint, nil);
end;
end;
end;
function TDOMVisitorFrm.HandleGetDocumentRslt(aSuccess : boolean; const aResult: ICefValue) : boolean;
var
TempRsltDict, TempRootNode : ICefDictionaryValue;
TempDocNodeID : integer;
begin
Result := False;
if aSuccess and (aResult <> nil) then
begin
TempRsltDict := aResult.GetDictionary;
if TCEFJson.ReadDictionary(TempRsltDict, 'root', TempRootNode) and
TCEFJson.ReadInteger(TempRootNode, 'nodeId', TempDocNodeID) and
(QuerySelector(TempDocNodeID, '#' + NODE_ID) <> 0) then
Result := True;
end
else
if not(HandleErrorRslt(aResult)) then
ErrorText := 'GetDocument was not successful!';
if not(Result) then
PostMessage(Handle, MINIBROWSER_SHOWERROR, 0, 0);
end;
function TDOMVisitorFrm.HandleQuerySelectorRslt(aSuccess : boolean; const aResult: ICefValue) : boolean;
var
TempRsltDict : ICefDictionaryValue;
TempNodeID : integer;
begin
Result := False;
if aSuccess and (aResult <> nil) then
begin
TempRsltDict := aResult.GetDictionary;
if TCEFJson.ReadInteger(TempRsltDict, 'nodeId', TempNodeID) and
(SetAttributeValue(TempNodeID, 'value', 'qwerty') <> 0) then
Result := True;
end
else
if not(HandleErrorRslt(aResult)) then
ErrorText := 'QuerySelector was not successful!';
if not(Result) then
PostMessage(Handle, MINIBROWSER_SHOWERROR, 0, 0);
end;
function TDOMVisitorFrm.HandleSetAttributeValueRslt(aSuccess : boolean; const aResult: ICefValue) : boolean;
begin
Result := False;
if aSuccess then
Result := True
else
if not(HandleErrorRslt(aResult)) then
ErrorText := 'SetAttributeValue was not successful!';
if not(Result) then
PostMessage(Handle, MINIBROWSER_SHOWERROR, 0, 0);
end;
function TDOMVisitorFrm.HandleErrorRslt(const aResult: ICefValue) : boolean;
var
TempRsltDict : ICefDictionaryValue;
TempCode : integer;
TempMessage : ustring;
begin
Result := False;
if (aResult <> nil) then
begin
TempRsltDict := aResult.GetDictionary;
if TCEFJson.ReadInteger(TempRsltDict, 'code', TempCode) and
TCEFJson.ReadString(TempRsltDict, 'message', TempMessage) then
begin
ErrorText := 'Error (' + inttostr(TempCode) + ') : ' + quotedstr(TempMessage);
Result := True;
end;
end;
end;
procedure TDOMVisitorFrm.Chromium1DevToolsMethodResult(Sender: TObject;
const browser: ICefBrowser; message_id: Integer; success: Boolean;
const result: ICefValue);
begin
case FStatus of
dvsGettingDocNodeID :
if HandleGetDocumentRslt(success, result) then
begin
FStatus := dvsQueryingSelector;
exit;
end;
dvsQueryingSelector :
if HandleQuerySelectorRslt(success, result) then
begin
FStatus := dvsSettingAttributeValue;
exit;
end;
dvsSettingAttributeValue :
HandleSetAttributeValueRslt(success, result);
end;
FStatus := dvsIdle;
end;
procedure TDOMVisitorFrm.Chromium1ProcessMessageReceived(Sender: TObject;
const browser: ICefBrowser; const frame: ICefFrame; sourceProcess: TCefProcessId;
const message: ICefProcessMessage; out Result: Boolean);
@ -387,16 +706,26 @@ begin
if (message.Name = DOMVISITOR_MSGNAME_PARTIAL) then
begin
ShowStatusText('DOM Visitor result text : ' + message.ArgumentList.GetString(0));
StatusText := 'DOM Visitor result text : ' + message.ArgumentList.GetString(0);
Result := True;
end
else
if (message.Name = DOMVISITOR_MSGNAME_FULL) then
begin
Clipboard.AsText := message.ArgumentList.GetString(0);
ShowStatusText('HTML copied to the clipboard');
StatusText := 'HTML copied to the clipboard';
Result := True;
end;
end
else
if (message.Name = FRAMEIDS_MSGNAME) then
begin
Clipboard.AsText := message.ArgumentList.GetString(0);
StatusText := 'Frame IDs copied to the clipboard in the render process.';
Result := True;
end;
if Result then
PostMessage(Handle, MINIBROWSER_SHOWSTATUSTEXT, 0, 0);
end;
procedure TDOMVisitorFrm.FormCloseQuery(Sender: TObject;
@ -416,6 +745,14 @@ procedure TDOMVisitorFrm.FormCreate(Sender: TObject);
begin
FCanClose := False;
FClosing := False;
FStatus := dvsIdle;
FCritSection := TCriticalSection.Create;
end;
procedure TDOMVisitorFrm.FormDestroy(Sender: TObject);
begin
FreeAndNil(FCritSection);
end;
procedure TDOMVisitorFrm.FormShow(Sender: TObject);
@ -430,11 +767,6 @@ begin
Chromium1.LoadURL(AddressEdt.Text);
end;
procedure TDOMVisitorFrm.CEFSentinel1Close(Sender: TObject);
begin
end;
procedure TDOMVisitorFrm.BrowserCreatedMsg(var aMessage : TMessage);
begin
CEFWindowParent1.UpdateSize;
@ -470,6 +802,67 @@ begin
Chromium1.SendProcessMessage(PID_RENDERER, TempMsg);
end;
procedure TDOMVisitorFrm.VisitDOM3Msg(var aMessage : TMessage);
var
TempJSCode, TempMessage : string;
begin
// Here we send the name and value of the element with the "console trick".
// We execute "console.log" in JavaScript to send TempMessage with a
// known preamble that will be used to identify the message in the
// TChromium.OnConsoleMessage event.
TempMessage := 'document.getElementById("' + NODE_ID + '").value';
TempJSCode := 'console.log("' + CONSOLE_MSG_PREAMBLE + '" + ' + TempMessage + ');';
chromium1.ExecuteJavaScript(TempJSCode, 'about:blank');
end;
procedure TDOMVisitorFrm.CopyFrameIDs1(var aMessage : TMessage);
var
i : NativeUInt;
TempCount : NativeUInt;
TempArray : TCefFrameIdentifierArray;
TempString : string;
begin
TempCount := Chromium1.FrameCount;
if Chromium1.GetFrameIdentifiers(TempCount, TempArray) then
begin
TempString := '';
i := 0;
while (i < TempCount) do
begin
TempString := TempString + inttostr(TempArray[i]) + CRLF;
inc(i);
end;
clipboard.AsText := TempString;
ShowStatusText('Frame IDs copied to the clipboard in the browser process (' + inttostr(TempCount) + ')');
end;
end;
procedure TDOMVisitorFrm.CopyFrameIDs2(var aMessage : TMessage);
var
TempMsg : ICefProcessMessage;
begin
TempMsg := TCefProcessMessageRef.New(FRAMEIDS_MSGNAME);
Chromium1.SendProcessMessage(PID_RENDERER, TempMsg);
end;
procedure TDOMVisitorFrm.ShowMessageMsg(var aMessage : TMessage);
begin
showmessage(MsgContents);
end;
procedure TDOMVisitorFrm.ShowStatusTextMsg(var aMessage : TMessage);
begin
ShowStatusText(StatusText);
end;
procedure TDOMVisitorFrm.ShowErrorMsg(var aMessage : TMessage);
begin
messagedlg(ErrorText, mtError, [mbOK], 0);
end;
procedure TDOMVisitorFrm.WMMove(var aMessage : TWMMove);
begin
inherited;
@ -489,6 +882,46 @@ begin
StatusPnl.Caption := aText;
end;
// https://chromedevtools.github.io/devtools-protocol/tot/DOM/#method-querySelector
function TDOMVisitorFrm.QuerySelector(aNodeID : integer; const aSelector : string) : integer;
var
TempParams : ICefDictionaryValue;
begin
Result := 0;
try
if (length(aSelector) > 0) then
begin
TempParams := TCefDictionaryValueRef.New;
TempParams.SetInt('nodeId', aNodeID);
TempParams.SetString('selector', aSelector);
Result := Chromium1.ExecuteDevToolsMethod(0, 'DOM.querySelector', TempParams);
end;
finally
TempParams := nil;
end;
end;
// https://chromedevtools.github.io/devtools-protocol/tot/DOM/#method-setAttributeValue
function TDOMVisitorFrm.SetAttributeValue(aNodeID : integer; const aName, aValue : string) : integer;
var
TempParams : ICefDictionaryValue;
begin
Result := 0;
try
if (aNodeID <> 0) then
begin
TempParams := TCefDictionaryValueRef.New;
TempParams.SetInt('nodeId', aNodeID);
TempParams.SetString('name', aName);
TempParams.SetString('value', aValue);
Result := Chromium1.ExecuteDevToolsMethod(0, 'DOM.setAttributeValue', TempParams);
end;
finally
TempParams := nil;
end;
end;
procedure TDOMVisitorFrm.Timer1Timer(Sender: TObject);
begin
Timer1.Enabled := False;
@ -496,4 +929,73 @@ begin
Timer1.Enabled := True;
end;
function TDOMVisitorFrm.GetMsgContents : string;
begin
Result := '';
if (FCritSection <> nil) then
try
FCritSection.Acquire;
Result := FMsgContents;
finally
FCritSection.Release;
end;
end;
procedure TDOMVisitorFrm.SetMsgContents(const aValue : string);
begin
if (FCritSection <> nil) then
try
FCritSection.Acquire;
FMsgContents := aValue;
finally
FCritSection.Release;
end;
end;
function TDOMVisitorFrm.GetStatusText : string;
begin
Result := '';
if (FCritSection <> nil) then
try
FCritSection.Acquire;
Result := FStatusText;
finally
FCritSection.Release;
end;
end;
procedure TDOMVisitorFrm.SetStatusText(const aValue : string);
begin
if (FCritSection <> nil) then
try
FCritSection.Acquire;
FStatusText := aValue;
finally
FCritSection.Release;
end;
end;
function TDOMVisitorFrm.GetErrorText : string;
begin
Result := '';
if (FCritSection <> nil) then
try
FCritSection.Acquire;
Result := FErrorText;
finally
FCritSection.Release;
end;
end;
procedure TDOMVisitorFrm.SetErrorText(const aValue : string);
begin
if (FCritSection <> nil) then
try
FCritSection.Acquire;
FErrorText := aValue;
finally
FCritSection.Release;
end;
end;
end.

View File

@ -2,7 +2,7 @@
"UpdateLazPackages" : [
{
"ForceNotify" : true,
"InternalVersion" : 176,
"InternalVersion" : 177,
"Name" : "cef4delphi_lazarus.lpk",
"Version" : "84.4.1.0"
}