unit uencapsulatedbrowser; {$mode objfpc}{$H+} interface uses SyncObjs, SysUtils, uCEFTypes, ucefbrowserthread; type TEncapsulatedBrowser = class protected FThread : TCEFBrowserThread; FWidth : integer; FHeight : integer; FDelayMs : integer; FScale : single; FSnapshotPath : string; FErrorText : string; procedure Thread_OnError(Sender: TObject); procedure Thread_OnSnapshotAvailable(Sender: TObject); public constructor Create; destructor Destroy; override; procedure LoadURL(const aURL : string); property Width : integer read FWidth write FWidth; property Height : integer read FHeight write FHeight; property SnapshotPath : string read FSnapshotPath write FSnapshotPath; property ErrorText : string read FErrorText; end; procedure CreateGlobalCEFApp; function WaitForMainAppEvent : boolean; procedure WriteResult; implementation uses uCEFApplication; var MainAppEvent : TSimpleEvent; EncapsulatedBrowser : TEncapsulatedBrowser = nil; procedure GlobalCEFApp_OnContextInitialized; var TempParam, TempURL : ustring; begin TempURL := ''; // This demo reads the "/url" parameter to load it as the default URL in the browser. // For example : ConsoleBrowser2.exe /url=https://www.briskbard.com if (ParamCount > 0) then begin TempParam := paramstr(1); if (Copy(TempParam, 1, 5) = '/url=') then begin TempURL := trim(Copy(TempParam, 6, length(TempParam))); if (length(TempURL) > 0) then WriteLn('Loading ' + TempURL); end; end; if (length(TempURL) = 0) then begin TempURL := 'https://www.google.com'; WriteLn('No URL has been specified. Using the default...'); end; EncapsulatedBrowser := TEncapsulatedBrowser.Create; EncapsulatedBrowser.LoadURL(TempURL); end; function WaitForMainAppEvent : boolean; begin Result := True; // Wait for 1 minute max. if (MainAppEvent.WaitFor(60000) = wrTimeout) then begin WriteLn('Timeout expired!'); Result := False; end; end; procedure WriteResult; begin if (EncapsulatedBrowser = nil) then WriteLn('There was a problem in the browser initialization') else if (length(EncapsulatedBrowser.ErrorText) > 0) then WriteLn(EncapsulatedBrowser.ErrorText) else WriteLn('Snapshot saved successfully as ' + EncapsulatedBrowser.SnapshotPath); end; procedure CreateGlobalCEFApp; begin GlobalCEFApp := TCefApplication.Create; GlobalCEFApp.WindowlessRenderingEnabled := True; GlobalCEFApp.ShowMessageDlg := False; // This demo shouldn't show any window, just console messages. GlobalCEFApp.BrowserSubprocessPath := 'consolebrowser_sp'; // This is the other EXE for the CEF subprocesses. It's on the same directory as this app. GlobalCEFApp.BlinkSettings := 'hideScrollbars'; // This setting removes all scrollbars to capture a cleaner snapshot GlobalCEFApp.OnContextInitialized := @GlobalCEFApp_OnContextInitialized; GlobalCEFApp.SetCurrentDir := True; GlobalCEFApp.DisableZygote := True; GlobalCEFApp.StartMainProcess; end; constructor TEncapsulatedBrowser.Create; begin inherited Create; FThread := nil; FWidth := 1024; FHeight := 768; FSnapshotPath := 'snapshot.png'; FErrorText := ''; end; destructor TEncapsulatedBrowser.Destroy; begin if (FThread <> nil) then begin FThread.TerminateBrowserThread; FThread.WaitFor; FreeAndNil(FThread); end; inherited Destroy; end; procedure TEncapsulatedBrowser.LoadURL(const aURL : string); begin if (FThread = nil) then begin FThread := TCEFBrowserThread.Create(FWidth, FHeight, aURL, FSnapshotPath); FThread.OnError := @Thread_OnError; FThread.OnSnapshotAvailable := @Thread_OnSnapshotAvailable; FThread.Start; end else FThread.LoadUrl(aURL); end; procedure TEncapsulatedBrowser.Thread_OnError(Sender: TObject); begin // This code is executed in the TCEFBrowserThread thread context while the main application thread is waiting for MainAppEvent. FErrorText := 'Error'; if (FThread.ErrorCode <> 0) then FErrorText := FErrorText + ' ' + inttostr(FThread.ErrorCode); FErrorText := FErrorText + ' : ' + FThread.ErrorText; if (length(FThread.FailedUrl) > 0) then FErrorText := FErrorText + ' - ' + FThread.FailedUrl; if assigned(MainAppEvent) then MainAppEvent.SetEvent; end; procedure TEncapsulatedBrowser.Thread_OnSnapshotAvailable(Sender: TObject); begin // This code is executed in the TCEFBrowserThread thread context while the main application thread is waiting for MainAppEvent. if assigned(MainAppEvent) then MainAppEvent.SetEvent; end; initialization MainAppEvent := TSimpleEvent.Create; finalization MainAppEvent.Free; if (EncapsulatedBrowser <> nil) then FreeAndNil(EncapsulatedBrowser); end.