2018-11-17 11:50:34 +01:00
// ************************************************************************
// ***************************** CEF4Delphi *******************************
// ************************************************************************
//
2019-10-19 10:58:34 +02:00
// CEF4Delphi is based on DCEF3 which uses CEF to embed a chromium-based
2018-11-17 11:50:34 +01:00
// browser in Delphi applications.
//
// The original license of DCEF3 still applies to CEF4Delphi.
//
// For more information about CEF4Delphi visit :
// https://www.briskbard.com/index.php?lang=en&pageid=cef
//
2020-01-01 12:48:10 +01:00
// Copyright <20> 2020 Salvador D<> az Fau. All rights reserved.
2018-11-17 11:50:34 +01:00
//
// ************************************************************************
// ************ vvvv Original license and comments below vvvv *************
// ************************************************************************
( *
* Delphi Chromium Embedded 3
*
* Usage allowed under the restrictions of the Lesser GNU General Public License
* or alternatively the restrictions of the Mozilla Public License 1.1
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
*
* Unit owner : Henri Gourvest < hgourvest@ gmail. com>
* Web site : http: //www.progdigy.com
* Repository : http: //code.google.com/p/delphichromiumembedded/
* Group : http: //groups.google.com/group/delphichromiumembedded
*
* Embarcadero Technologies, Inc is not permitted to use or redistribute
* this source code without explicit permission.
*
* )
unit uURLRequest;
interface
uses
{$IFDEF DELPHI16_UP}
Winapi . Windows, Winapi . Messages, System. SysUtils, System. Variants, System. Classes, Vcl. Graphics,
Vcl. Controls, Vcl. Forms, Vcl. Dialogs, Vcl. ComCtrls, Vcl. StdCtrls,
{$ELSE}
Windows, Messages, SysUtils, Variants, Classes, Graphics,
Controls, Forms, Dialogs, ComCtrls, StdCtrls,
{$ENDIF}
2019-10-13 18:50:23 +02:00
uCEFInterfaces, uCEFUrlRequestClientComponent, uCEFRequest, uCEFUrlRequest,
uCEFSentinel;
2018-11-17 11:50:34 +01:00
const
URLREQUEST_SUCCESS = WM_APP + $101 ;
URLREQUEST_ERROR = WM_APP + $102 ;
type
TURLRequestFrm = class( TForm)
StatusBar1: TStatusBar;
SaveDialog1: TSaveDialog;
CEFUrlRequestClientComponent1: TCEFUrlRequestClientComponent;
2019-09-25 17:23:16 +02:00
GETGbx: TGroupBox;
DownloadBtn: TButton;
GetURLEdt: TEdit;
Label1: TLabel;
POSTGbx: TGroupBox;
PostURLEdt: TEdit;
Label2: TLabel;
SendPostReqBtn: TButton;
Button1: TButton;
GroupBox1: TGroupBox;
Label3: TLabel;
PostParam1NameEdt: TEdit;
Label4: TLabel;
PostParam1ValueEdt: TEdit;
GroupBox2: TGroupBox;
Label5: TLabel;
Label6: TLabel;
PostParam2NameEdt: TEdit;
PostParam2ValueEdt: TEdit;
2018-11-17 11:50:34 +01:00
procedure DownloadBtnClick( Sender: TObject) ;
2019-09-25 17:23:16 +02:00
procedure SendPostReqBtnClick( Sender: TObject) ;
2019-10-13 18:50:23 +02:00
procedure Button1Click( Sender: TObject) ;
2018-11-17 11:50:34 +01:00
procedure FormDestroy( Sender: TObject) ;
procedure FormCreate( Sender: TObject) ;
procedure FormCloseQuery( Sender: TObject; var CanClose: Boolean ) ;
procedure CEFUrlRequestClientComponent1DownloadData( Sender: TObject; const request: ICefUrlRequest; data: Pointer ; dataLength: NativeUInt ) ;
procedure CEFUrlRequestClientComponent1DownloadProgress( Sender: TObject; const request: ICefUrlRequest; current, total: Int64 ) ;
procedure CEFUrlRequestClientComponent1RequestComplete( Sender: TObject; const request: ICefUrlRequest) ;
procedure CEFUrlRequestClientComponent1CreateURLRequest( Sender: TObject) ;
2019-08-27 09:52:33 +02:00
2018-11-17 11:50:34 +01:00
private
2019-09-25 17:23:16 +02:00
FMemStream : TMemoryStream;
2018-11-17 11:50:34 +01:00
FCanClose : boolean ;
FClosing : boolean ;
2019-09-25 17:23:16 +02:00
FBusy : boolean ;
2018-11-17 11:50:34 +01:00
FPendingURL : string ;
2019-09-25 17:23:16 +02:00
FSendingGET : boolean ;
FSendingPOST : boolean ;
procedure CreateGETRequest;
procedure CreatePOSTRequest;
2018-11-17 11:50:34 +01:00
procedure URLRequestSuccessMsg( var aMessage : TMessage) ; message URLREQUEST_SUCCESS;
procedure URLRequestErrorMsg( var aMessage : TMessage) ; message URLREQUEST_ERROR;
procedure SaveStreamToFile;
end ;
var
URLRequestFrm: TURLRequestFrm;
2019-09-25 17:23:16 +02:00
procedure CreateGlobalCEFApp;
2018-11-17 11:50:34 +01:00
implementation
{$R *.dfm}
// This is a simple URL request example to download small files using TCEFUrlRequestClientComponent.
// WARNING : If you try to download big files you may get an "Out of memory" exception. Replace TMemoryStream in that case.
// All TCEFUrlRequestClientComponent events are executed in a different thread. Don't create or destroy VCL componets
// inside them.
// To keep this demo as simple as possible, it's only allowed to download one file at a time. You can add as many requests
// as you want but then you would have to use a different way to store the data with synchronization objects.
// It's much safer to cancel all requests before closing the app.
// This demo follows this destruction sequence in case there is a file download running :
// --------------------------------------------------------------------------------------
// 1- Set CanClose to FALSE in the TForm.OnCloseQuery event and set FClosing to TRUE.
// 2- The next time TCEFUrlRequestClientComponent.OnDownloadProgress is executed we call request.Cancel, which triggers the
// TCEFUrlRequestClientComponent.OnRequestComplete event.
2019-10-13 18:50:23 +02:00
// 3- in the TCEFUrlRequestClientComponent.OnRequestComplete event we call TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed.
// 4- TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form.
2018-11-17 11:50:34 +01:00
uses
2019-09-25 17:23:16 +02:00
ShellApi,
uCEFApplication, uCEFMiscFunctions, uCEFTypes, uCEFPostData, uCEFPostDataElement, uCEFConstants;
procedure CreateGlobalCEFApp;
begin
GlobalCEFApp : = TCefApplication. Create;
2019-10-01 18:47:24 +02:00
//GlobalCEFApp.LogFile := 'cef.log';
//GlobalCEFApp.LogSeverity := LOGSEVERITY_VERBOSE;
2019-09-25 17:23:16 +02:00
end ;
2018-11-17 11:50:34 +01:00
procedure TURLRequestFrm. DownloadBtnClick( Sender: TObject) ;
var
TempURL, TempPath, TempName : string ;
TempParts : TUrlParts;
i : integer ;
begin
2019-09-25 17:23:16 +02:00
TempURL : = trim( GetURLEdt. Text ) ;
2018-11-17 11:50:34 +01:00
if ( length( TempURL) > 0 ) then
begin
CefParseUrl( TempURL, TempParts) ;
TempPath : = trim( TempParts. path) ;
TempName : = '' ;
if ( length( TempPath) > 0 ) then
begin
i : = LastDelimiter( '/' , TempPath) ;
if ( i > 0 ) then
TempName : = trim( copy( TempPath, succ( i) , length( TempPath) ) )
else
TempName : = TempPath;
end ;
if ( length( TempName) > 0 ) then
SaveDialog1. FileName : = TempName // This name should be decoded and sanitized before using it in Windows
else
SaveDialog1. FileName : = 'UnknownFileName' ;
if SaveDialog1. Execute and
( length( SaveDialog1. FileName) > 0 ) then
begin
FPendingURL : = TempURL;
2019-09-25 17:23:16 +02:00
GETGbx. Enabled : = False ;
POSTGbx. Enabled : = False ;
2018-11-17 11:50:34 +01:00
StatusBar1. Panels[ 0 ] . Text : = 'Downloading...' ;
2019-09-25 17:23:16 +02:00
FMemStream. Clear;
FSendingPOST : = False ;
FSendingGET : = True ;
2018-11-17 11:50:34 +01:00
// TCEFUrlRequestClientComponent.AddURLRequest will trigger the
// TCEFUrlRequestClientComponent.OnCreateURLRequest event in the right
// thread where you can create your custom requests.
CEFUrlRequestClientComponent1. AddURLRequest;
end ;
end ;
end ;
procedure TURLRequestFrm. FormCloseQuery( Sender: TObject; var CanClose: Boolean ) ;
begin
2019-09-25 17:23:16 +02:00
CanClose : = FCanClose or not( FBusy) ;
2018-11-17 11:50:34 +01:00
FClosing : = True ;
end ;
procedure TURLRequestFrm. FormCreate( Sender: TObject) ;
begin
2019-09-25 17:23:16 +02:00
FMemStream : = TMemoryStream. Create;
2018-11-17 11:50:34 +01:00
FCanClose : = False ;
FClosing : = False ;
2019-09-25 17:23:16 +02:00
FBusy : = False ;
FSendingGET : = False ;
FSendingPOST : = False ;
2018-11-17 11:50:34 +01:00
end ;
procedure TURLRequestFrm. FormDestroy( Sender: TObject) ;
begin
2019-09-25 17:23:16 +02:00
if ( FMemStream < > nil ) then FreeAndNil( FMemStream) ;
end ;
procedure TURLRequestFrm. Button1Click( Sender: TObject) ;
begin
ShellExecute( 0 , 'open' , 'https://ptsv2.com/t/cef4delphi' , nil , nil , SW_SHOWNORMAL) ;
2018-11-17 11:50:34 +01:00
end ;
procedure TURLRequestFrm. CEFUrlRequestClientComponent1CreateURLRequest( Sender: TObject) ;
2019-09-25 17:23:16 +02:00
begin
if FSendingGET then
CreateGETRequest
else
if FSendingPOST then
CreatePOSTRequest;
end ;
procedure TURLRequestFrm. CreateGETRequest;
2018-11-17 11:50:34 +01:00
var
TempRequest : ICefRequest;
begin
try
if ( length( FPendingURL) > 0 ) then
begin
2019-09-25 17:23:16 +02:00
FBusy : = True ;
2018-11-17 11:50:34 +01:00
TempRequest : = TCefRequestRef. New;
TempRequest. URL : = FPendingURL;
TempRequest. Method : = 'GET' ;
2018-12-09 11:11:59 +01:00
TempRequest. Flags : = UR_FLAG_ALLOW_STORED_CREDENTIALS;
2018-11-17 11:50:34 +01:00
// Set the "client" parameter to the TCEFUrlRequestClientComponent.Client property
// to use the TCEFUrlRequestClientComponent events.
// The "requestContext" parameter can be nil to use the global request context.
TCefUrlRequestRef. New( TempRequest, CEFUrlRequestClientComponent1. Client, nil ) ;
end ;
finally
TempRequest : = nil ;
end ;
end ;
2019-09-25 17:23:16 +02:00
procedure TURLRequestFrm. CreatePOSTRequest;
var
TempRequest : ICefRequest;
TempPostData : ICefPostData;
TempElement : ICefPostDataElement;
TempParams : AnsiString ;
begin
try
if ( length( FPendingURL) > 0 ) then
begin
FBusy : = True ;
TempRequest : = TCefRequestRef. New;
TempRequest. URL : = FPendingURL;
TempRequest. Method : = 'POST' ;
TempRequest. Flags : = UR_FLAG_ALLOW_STORED_CREDENTIALS;
// TODO : The parameters should be converted to ansistring and encoded
if ( length( PostParam1NameEdt. Text ) > 0 ) and ( length( PostParam1ValueEdt. Text ) > 0 ) then
TempParams : = PostParam1NameEdt. Text + '=' + PostParam1ValueEdt. Text ;
if ( length( PostParam2NameEdt. Text ) > 0 ) and ( length( PostParam2ValueEdt. Text ) > 0 ) then
begin
if ( length( TempParams) > 0 ) then
TempParams : = TempParams + '&' + PostParam2NameEdt. Text + '=' + PostParam2ValueEdt. Text
else
TempParams : = PostParam2NameEdt. Text + '=' + PostParam2ValueEdt. Text ;
end ;
if ( length( TempParams) > 0 ) then
begin
TempElement : = TCefPostDataElementRef. New;
TempElement. SetToBytes( length( TempParams) , @ TempParams[ 1 ] ) ;
TempPostData : = TCefPostDataRef. New;
TempPostData. AddElement( TempElement) ;
TempRequest. PostData : = TempPostData;
// Set the "client" parameter to the TCEFUrlRequestClientComponent.Client property
// to use the TCEFUrlRequestClientComponent events.
// The "requestContext" parameter can be nil to use the global request context.
TCefUrlRequestRef. New( TempRequest, CEFUrlRequestClientComponent1. Client, nil ) ;
end ;
end ;
finally
TempElement : = nil ;
TempPostData : = nil ;
TempRequest : = nil ;
end ;
end ;
2018-11-17 11:50:34 +01:00
procedure TURLRequestFrm. CEFUrlRequestClientComponent1DownloadData( Sender: TObject; const request: ICefUrlRequest; data: Pointer ; dataLength: NativeUInt ) ;
begin
try
if FClosing then
request. Cancel
else
2019-09-25 17:23:16 +02:00
if FSendingGET then
begin
if ( data < > nil ) and ( dataLength > 0 ) then
FMemStream. WriteBuffer( data^ , dataLength) ;
end ;
2018-11-17 11:50:34 +01:00
except
on e : exception do
if CustomExceptionHandler( 'TURLRequestFrm.CEFUrlRequestClientComponent1DownloadData' , e) then raise ;
end ;
end ;
procedure TURLRequestFrm. CEFUrlRequestClientComponent1DownloadProgress( Sender: TObject; const request: ICefUrlRequest; current, total: Int64 ) ;
begin
if FClosing then
request. Cancel
else
2019-09-25 17:23:16 +02:00
if FSendingGET then
begin
if ( total > 0 ) then
StatusBar1. Panels[ 0 ] . Text : = 'Downloading : ' + inttostr( round( ( current / total) * 1 0 0 ) ) + ' %'
else
StatusBar1. Panels[ 0 ] . Text : = 'Downloading : ' + inttostr( current) + ' bytes' ;
end ;
2018-11-17 11:50:34 +01:00
end ;
procedure TURLRequestFrm. CEFUrlRequestClientComponent1RequestComplete( Sender: TObject; const request: ICefUrlRequest) ;
begin
2019-09-25 17:23:16 +02:00
FBusy : = False ;
2018-11-17 11:50:34 +01:00
// Use request.response here to get a ICefResponse interface with all the response headers, status, error code, etc.
if FClosing then
2019-11-27 10:42:42 +01:00
begin
FCanClose : = True ;
PostMessage( Handle, WM_CLOSE, 0 , 0 ) ;
end
2018-11-17 11:50:34 +01:00
else
if ( request < > nil ) and ( request. RequestStatus = UR_SUCCESS) then
PostMessage( Handle, URLREQUEST_SUCCESS, 0 , 0 )
else
PostMessage( Handle, URLREQUEST_ERROR, 0 , request. RequestError) ;
end ;
procedure TURLRequestFrm. URLRequestSuccessMsg( var aMessage : TMessage) ;
2019-09-25 17:23:16 +02:00
var
TempMessage : string ;
2018-11-17 11:50:34 +01:00
begin
2019-09-25 17:23:16 +02:00
if FSendingGET then
begin
TempMessage : = 'Download complete!' ;
SaveStreamToFile;
end
else
if FSendingPOST then
TempMessage : = 'Parameters sent!' ;
StatusBar1. Panels[ 0 ] . Text : = TempMessage;
showmessage( TempMessage) ;
GETGbx. Enabled : = True ;
POSTGbx. Enabled : = True ;
FSendingGET : = False ;
FSendingPOST : = False ;
2018-11-17 11:50:34 +01:00
end ;
procedure TURLRequestFrm. URLRequestErrorMsg( var aMessage : TMessage) ;
2019-09-25 17:23:16 +02:00
var
TempMessage : string ;
2018-11-17 11:50:34 +01:00
begin
2019-09-25 17:23:16 +02:00
TempMessage : = 'Error code : ' + inttostr( aMessage. lParam) ;
StatusBar1. Panels[ 0 ] . Text : = TempMessage;
showmessage( TempMessage) ;
GETGbx. Enabled : = True ;
POSTGbx. Enabled : = True ;
FSendingGET : = False ;
FSendingPOST : = False ;
2018-11-17 11:50:34 +01:00
end ;
procedure TURLRequestFrm. SaveStreamToFile;
begin
try
2019-09-25 17:23:16 +02:00
FMemStream. SaveToFile( SaveDialog1. FileName) ;
FMemStream. Clear;
2018-11-17 11:50:34 +01:00
except
on e : exception do
if CustomExceptionHandler( 'TURLRequestFrm.SaveStreamToFile' , e) then raise ;
end ;
end ;
2019-09-25 17:23:16 +02:00
procedure TURLRequestFrm. SendPostReqBtnClick( Sender: TObject) ;
var
TempURL : string ;
begin
TempURL : = trim( PostURLEdt. Text ) ;
if ( length( TempURL) > 0 ) then
begin
FPendingURL : = TempURL;
GETGbx. Enabled : = False ;
POSTGbx. Enabled : = False ;
StatusBar1. Panels[ 0 ] . Text : = 'Sending...' ;
FMemStream. Clear;
FSendingPOST : = True ;
FSendingGET : = False ;
// TCEFUrlRequestClientComponent.AddURLRequest will trigger the
// TCEFUrlRequestClientComponent.OnCreateURLRequest event in the right
// thread where you can create your custom requests.
CEFUrlRequestClientComponent1. AddURLRequest;
end ;
end ;
2018-11-17 11:50:34 +01:00
end .