diff --git a/Examples/DOMAccess/dom.ico b/Examples/DOMAccess/dom.ico new file mode 100644 index 0000000..0341321 Binary files /dev/null and b/Examples/DOMAccess/dom.ico differ diff --git a/Examples/DOMAccess/dom.lpi b/Examples/DOMAccess/dom.lpi new file mode 100644 index 0000000..a58a6c9 --- /dev/null +++ b/Examples/DOMAccess/dom.lpi @@ -0,0 +1,211 @@ + + + + + + + + + <ResourceType Value="res"/> + <UseXPManifest Value="True"/> + <Icon Value="0"/> + </General> + <i18n> + <EnableI18N LFM="False"/> + </i18n> + <VersionInfo> + <StringTable ProductVersion=""/> + </VersionInfo> + <MacroValues Count="1"> + <Macro1 Name="LCLWidgetType" Value="gtk2"/> + </MacroValues> + <BuildModes Count="3"> + <Item1 Name="Linux" Default="True"/> + <Item2 Name="Win32"> + <MacroValues Count="1"> + <Macro2 Name="LCLWidgetType" Value="win32"/> + </MacroValues> + <CompilerOptions> + <Version Value="11"/> + <Target> + <Filename Value="simple32"/> + </Target> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)"/> + <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/> + </SearchPaths> + <Parsing> + <SyntaxOptions> + <AllowLabel Value="False"/> + </SyntaxOptions> + </Parsing> + <CodeGeneration> + <RelocatableUnit Value="True"/> + <Checks> + <IOChecks Value="True"/> + <RangeChecks Value="True"/> + <OverflowChecks Value="True"/> + </Checks> + <TargetCPU Value="i386"/> + <TargetOS Value="win32"/> + </CodeGeneration> + <Linking> + <Options> + <Win32> + <GraphicApplication Value="True"/> + </Win32> + </Options> + </Linking> + <Other> + <CompilerMessages> + <UseMsgFile Value="True"/> + </CompilerMessages> + <CompilerPath Value="$(CompPath)"/> + </Other> + </CompilerOptions> + </Item2> + <Item3 Name="Win64"> + <MacroValues Count="1"> + <Macro2 Name="LCLWidgetType" Value="win32"/> + </MacroValues> + <CompilerOptions> + <Version Value="11"/> + <Target> + <Filename Value="simple64"/> + </Target> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)"/> + <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/> + </SearchPaths> + <Parsing> + <SyntaxOptions> + <AllowLabel Value="False"/> + </SyntaxOptions> + </Parsing> + <CodeGeneration> + <RelocatableUnit Value="True"/> + <Checks> + <IOChecks Value="True"/> + <RangeChecks Value="True"/> + <OverflowChecks Value="True"/> + </Checks> + <TargetCPU Value="x86_64"/> + <TargetOS Value="win64"/> + </CodeGeneration> + <Linking> + <Options> + <Win32> + <GraphicApplication Value="True"/> + </Win32> + </Options> + </Linking> + <Other> + <CompilerMessages> + <UseMsgFile Value="True"/> + </CompilerMessages> + <CompilerPath Value="$(CompPath)"/> + </Other> + </CompilerOptions> + </Item3> + <SharedMatrixOptions Count="2"> + <Item1 ID="661871476567" Modes="Linux" Type="IDEMacro" MacroName="LCLWidgetType" Value="gtk2"/> + <Item2 ID="279904151772" Modes="Win32,Win64" Type="IDEMacro" MacroName="LCLWidgetType" Value="win32"/> + </SharedMatrixOptions> + </BuildModes> + <PublishOptions> + <Version Value="2"/> + <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/> + <ExcludeFileFilter Value="*.(bak|ppu|o|so);*~;backup"/> + </PublishOptions> + <RunParams> + <local> + <FormatVersion Value="1"/> + </local> + <environment> + <UserOverrides Count="1"> + <Variable0 Name="LD_LIBRARY_PATH" Value="."/> + </UserOverrides> + </environment> + </RunParams> + <RequiredPackages Count="2"> + <Item1> + <PackageName Value="CEF3"/> + </Item1> + <Item2> + <PackageName Value="LCL"/> + </Item2> + </RequiredPackages> + <Units Count="3"> + <Unit0> + <Filename Value="dom.lpr"/> + <IsPartOfProject Value="True"/> + <UnitName Value="dom"/> + </Unit0> + <Unit1> + <Filename Value="main.pas"/> + <IsPartOfProject Value="True"/> + <ComponentName Value="Mainform"/> + <HasResources Value="True"/> + <ResourceBaseClass Value="Form"/> + <UnitName Value="Main"/> + </Unit1> + <Unit2> + <Filename Value="handler.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="Handler"/> + </Unit2> + </Units> + </ProjectOptions> + <CompilerOptions> + <Version Value="11"/> + <Target> + <Filename Value="dom"/> + </Target> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)"/> + <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/> + </SearchPaths> + <Parsing> + <SyntaxOptions> + <IncludeAssertionCode Value="True"/> + <AllowLabel Value="False"/> + </SyntaxOptions> + </Parsing> + <CodeGeneration> + <Checks> + <IOChecks Value="True"/> + <RangeChecks Value="True"/> + <OverflowChecks Value="True"/> + <StackChecks Value="True"/> + </Checks> + <TargetCPU Value="x86_64"/> + <TargetOS Value="linux"/> + </CodeGeneration> + <Linking> + <Options> + <Win32> + <GraphicApplication Value="True"/> + </Win32> + </Options> + </Linking> + <Other> + <CompilerMessages> + <UseMsgFile Value="True"/> + </CompilerMessages> + <CompilerPath Value="$(CompPath)"/> + </Other> + </CompilerOptions> + <Debugging> + <Exceptions Count="3"> + <Item1> + <Name Value="EAbort"/> + </Item1> + <Item2> + <Name Value="ECodetoolError"/> + </Item2> + <Item3> + <Name Value="EFOpenError"/> + </Item3> + </Exceptions> + </Debugging> +</CONFIG> diff --git a/Examples/DOMAccess/dom.lpr b/Examples/DOMAccess/dom.lpr new file mode 100644 index 0000000..09e01c7 --- /dev/null +++ b/Examples/DOMAccess/dom.lpr @@ -0,0 +1,21 @@ +Program dom; + +{$MODE objfpc}{$H+} + +Uses + {$IFDEF UNIX} + cthreads, + {$ENDIF} + Interfaces, // this includes the LCL widgetset + Forms, Main, handler; + +{$R *.res} + +begin + Application.Title := 'DOMAccess'; + RequireDerivedFormResource := True; + Application.Initialize; + Application.CreateForm(TMainform, Mainform); + Application.Run; +end. + diff --git a/Examples/DOMAccess/handler.pas b/Examples/DOMAccess/handler.pas new file mode 100644 index 0000000..8e45183 --- /dev/null +++ b/Examples/DOMAccess/handler.pas @@ -0,0 +1,86 @@ +Unit Handler; + +{$MODE objfpc}{$H+} + +(* + * Everything in here is called from a render process, so there is no access to GUI and all the + * data of the main process. + *) + +Interface + +Uses + Classes, SysUtils, + cef3types, cef3intf, cef3ref, cef3own; + +Type + { Custom handler for the render process } + TCustomRenderProcessHandler = class(TCefRenderProcessHandlerOwn) + protected + function OnProcessMessageReceived(const browser: ICefBrowser; sourceProcess: TCefProcessId; + const message: ICefProcessMessage): Boolean; override; + end; + +Implementation + +Var + // Don't access outside of callbacks + // Enables access to browser in callbacks, necessary unless nestedprocvars is used + ActiveBrowser: ICefBrowser; + +procedure visitDOM(const document: ICefDomDocument); +Var + message: ICefProcessMessage; +begin + message := TCefProcessMessageRef.New('domdata'); + With message.ArgumentList do + begin + SetString(0, document.GetTitle); + SetString(1, document.GetSelectionAsText); + end; + + ActiveBrowser.SendProcessMessage(PID_BROWSER, message); +end; + +procedure clickListener(const event: ICefDomEvent); +Var + message: ICefProcessMessage; +begin + message := TCefProcessMessageRef.New('click'); + With message.ArgumentList do + begin + SetString(0, event.Target.Name); + end; + + ActiveBrowser.SendProcessMessage(PID_BROWSER, message); +end; + +procedure registerListener(const document: ICefDomDocument); +begin + document.Body.AddEventListenerProc('click', False, @clickListener); +end; + +{ TCustomRenderProcessHandler } + +function TCustomRenderProcessHandler.OnProcessMessageReceived(const browser : ICefBrowser; + sourceProcess : TCefProcessId; const message : ICefProcessMessage) : Boolean; +begin + ActiveBrowser := browser; + Case message.Name of + 'visitdom': + begin + browser.MainFrame.VisitDomProc(@visitDOM); + Result := True; + end; + 'addListener': + begin + browser.MainFrame.VisitDomProc(@registerListener); + Result := True; + end; + Else + Result := inherited; + end; +end; + +end. + diff --git a/Examples/DOMAccess/main.lfm b/Examples/DOMAccess/main.lfm new file mode 100644 index 0000000..8f89102 --- /dev/null +++ b/Examples/DOMAccess/main.lfm @@ -0,0 +1,89 @@ +object Mainform: TMainform + Left = 370 + Height = 587 + Top = 38 + Width = 921 + Anchors = [] + Caption = 'Browser -' + ClientHeight = 587 + ClientWidth = 921 + OnCreate = FormCreate + LCLVersion = '1.2.2.0' + object Chromium: TChromium + AnchorSideLeft.Control = Owner + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = Owner + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = Log + Left = 0 + Height = 400 + Top = 48 + Width = 921 + Anchors = [akTop, akLeft, akRight, akBottom] + DefaultUrl = 'www.google.de' + TabOrder = 0 + OnProcessMessageReceived = ChromiumProcessMessageReceived + OnLoadEnd = ChromiumLoadEnd + OnKeyEvent = ChromiumKeyEvent + OnTitleChange = ChromiumTitleChange + end + object BGo: TButton + AnchorSideTop.Control = Owner + AnchorSideRight.Control = Owner + AnchorSideRight.Side = asrBottom + Left = 837 + Height = 25 + Top = 10 + Width = 79 + Anchors = [akTop, akRight] + BorderSpacing.Top = 10 + BorderSpacing.Right = 5 + Caption = 'Go' + OnClick = BGoClick + TabOrder = 1 + end + object LUrl: TStaticText + AnchorSideTop.Control = Owner + Left = 8 + Height = 22 + Top = 12 + Width = 25 + BorderSpacing.Top = 12 + Caption = 'Url:' + Font.Style = [fsBold] + ParentFont = False + TabOrder = 2 + end + object EUrl: TEdit + AnchorSideLeft.Control = LUrl + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = Owner + AnchorSideRight.Control = BGo + Left = 38 + Height = 25 + Top = 10 + Width = 794 + Anchors = [akTop, akLeft, akRight] + AutoSize = False + BorderSpacing.Left = 5 + BorderSpacing.Top = 10 + BorderSpacing.Right = 5 + OnKeyDown = EUrlKeyDown + TabOrder = 3 + Text = 'http://' + end + object Log: TMemo + AnchorSideLeft.Control = Owner + AnchorSideRight.Control = Owner + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = Owner + AnchorSideBottom.Side = asrBottom + Left = 0 + Height = 139 + Top = 448 + Width = 921 + Anchors = [akLeft, akRight, akBottom] + ScrollBars = ssAutoVertical + TabOrder = 4 + end +end diff --git a/Examples/DOMAccess/main.pas b/Examples/DOMAccess/main.pas new file mode 100644 index 0000000..b2b063f --- /dev/null +++ b/Examples/DOMAccess/main.pas @@ -0,0 +1,118 @@ +Unit Main; + +{$MODE objfpc}{$H+} + +Interface + +Uses + Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, LCLType, ExtCtrls, + cef3types, cef3lib, cef3intf, cef3ref, cef3lcl, + Handler; // custom render process handler + +Type + + { TMainform } + + TMainform = class(TForm) + BGo : TButton; + Chromium : TChromium; + EUrl : TEdit; + LUrl : TStaticText; + Log : TMemo; + procedure BGoClick(Sender : TObject); + procedure ChromiumKeyEvent(Sender : TObject; const Browser : ICefBrowser; + const event : PCefKeyEvent; osEvent : TCefEventHandle; out Result : Boolean); + procedure ChromiumLoadEnd(Sender : TObject; const Browser : ICefBrowser; + const Frame : ICefFrame; httpStatusCode : Integer); + procedure ChromiumProcessMessageReceived(Sender : TObject; + const Browser : ICefBrowser; sourceProcess : TCefProcessId; + const message : ICefProcessMessage; out Result : Boolean); + procedure ChromiumTitleChange(Sender : TObject; const Browser : ICefBrowser; + const title : ustring); + procedure EUrlKeyDown(Sender : TObject; var Key : Word; Shift : TShiftState); + procedure FormCreate(Sender : TObject); + private + { private declarations } + public + { public declarations } + end; + +Var + Mainform : TMainform; + +Implementation + +{$R *.lfm} + +{ TMainform } + +procedure TMainform.BGoClick(Sender : TObject); +begin + Chromium.Load(EUrl.Text); +end; + +procedure TMainform.ChromiumKeyEvent(Sender : TObject; const Browser : ICefBrowser; + const event : PCefKeyEvent; osEvent : TCefEventHandle; out Result : Boolean); +begin + If event^.kind = KEYEVENT_KEYUP then + begin + If Browser.SendProcessMessage(PID_RENDERER,TCefProcessMessageRef.New('visitdom')) then + Log.Append('Triggered DOM visit.') + Else Log.Append('Failed to start DOM visit.'); + + Result := True; + end; +end; + +procedure TMainform.ChromiumLoadEnd(Sender : TObject; const Browser : ICefBrowser; const Frame : ICefFrame; + httpStatusCode : Integer); +begin + EUrl.Text := UTF8Encode(Browser.MainFrame.Url); + + If Browser.SendProcessMessage(PID_RENDERER, TCefProcessMessageRef.New('addListener')) then + Log.Append('Listener registered.') + Else Log.Append('Failed to register listener.'); +end; + +procedure TMainform.ChromiumProcessMessageReceived(Sender : TObject; + const Browser : ICefBrowser; sourceProcess : TCefProcessId; + const message : ICefProcessMessage; out Result : Boolean); +begin + Case message.Name of + 'domdata': + begin + With message.ArgumentList do + begin + Log.Append('Title: ' + GetString(0)); + Log.Append('Selection: ' + GetString(1)); + end; + Result := True; + end; + 'click': + begin + Log.Append('Clicked: ' + message.ArgumentList.GetString(0)); + end; + Else + Log.Append('Unhandled message: ' + message.Name); + inherited; + end; +end; + +procedure TMainform.ChromiumTitleChange(Sender : TObject; const Browser : ICefBrowser; const title : ustring); +begin + Caption := 'Browser - ' + UTF8Encode(title); +end; + +procedure TMainform.EUrlKeyDown(Sender : TObject; var Key : Word; Shift : TShiftState); +begin + If Key = VK_RETURN then BGoClick(Sender); +end; + +procedure TMainform.FormCreate(Sender : TObject); +begin + // No subprocess here + // If you want to use a subprocess, this CefRenderProcessHandler has to be registered in subprocess + CefRenderProcessHandler := TCustomRenderProcessHandler.Create; +end; + +end. diff --git a/Examples/Examples.txt b/Examples/Examples.txt new file mode 100644 index 0000000..80952be --- /dev/null +++ b/Examples/Examples.txt @@ -0,0 +1,17 @@ +DOMAccess + Shows how to access DOM and transfer data between main process and render processes + + Thanks to zbyna for sharing his findings: + http://forum.lazarus.freepascal.org/index.php/topic,20103.msg149867.html#msg149867 + +GTK2Minimal + Minimal gtk2 example, doesn't use LCL and classes, direct use of cef3api + +LCLSimple + Simple LCL example to get started + +SubProcess + Minimal subprocess, can be used as is as long as no custom render handler is needed + +WinMinimal + Windows counterpart to gtk2 example