Map Delphi object events in V8 handlers
Posted: Tue Apr 06, 2021 5:54 pm
I've been using CEF4Delphi to develop some desktop applications using the React framework as the application GUI. The integration between my Delphi classes and the V8 engine is working nicely, but I'm facing a situation with Delphi objects events I'm not being able to handle.
I made the following extension to work with ZIP files in my JS scripts:
The exposition of the TZipFile class properties and events is working perfectly. I'm able to work with ZIP files in my JS scripts, but I would like also to have the TZipFile event "OnProgress" as part of my solution, so I could have a JS callback function to follow the progress of file operations. The truth is that I'm stucked because I just did not figure I proper way to integrate the Delphi native object events in my V8 extensions. Does anyone already achieved such functionality? Is there a way to do it? Thanks in advance.
I made the following extension to work with ZIP files in my JS scripts:
Code: Select all
unit uV8ObjZipHandler;
{$I cef.inc}
interface
uses
Winapi.Windows,
System.Classes, System.Zip, System.SysUtils,
uCEFTypes, uCEFInterfaces, uCEFv8Value, uCEFv8Handler, uCEFProcessMessage, uCEFv8Context;
type
TV8ZipFileObjHandler = class(TCefv8HandlerOwn)
FZip: TZipFile;
procedure _OnProgress(Sender: TObject; FileName: string; Header: TZipHeader; Position: Int64);
protected
FExtensionCode, FComment: string;
FUTF8Support: Boolean;
function Execute(const name: ustring; const obj: ICefv8Value; const arguments: TCefv8ValueArray; var retval: ICefv8Value; var _exception: ustring): Boolean; override;
public
constructor Create; override;
destructor Destroy; override;
property ExtensionCode: String read FExtensionCode;
end;
implementation
{ TV8ZipFileObjHandler }
constructor TV8ZipFileObjHandler.Create;
begin
inherited;
FZip := TZipFile.Create();
FZip.OnProgress := _OnProgress;
FExtensionCode :=
// Constants
// Mode
'const zmClosed = ' + UIntToStr(Cardinal(TZipMode.zmClosed)) + ';' +
'const zmRead = ' + UIntToStr(Cardinal(TZipMode.zmRead)) + ';' +
'const zmWrite = ' + UIntToStr(Cardinal(TZipMode.zmWrite)) + ';' +
'const zmReadWrite = ' + UIntToStr(Cardinal(TZipMode.zmReadWrite)) + ';' +
// Compression
'const zcStored = ' + UIntToStr(Cardinal(TZipCompression.zcStored)) + ';' +
'const zcShrunk = ' + UIntToStr(Cardinal(TZipCompression.zcShrunk)) + ';' +
'const zcReduce1 = ' + UIntToStr(Cardinal(TZipCompression.zcReduce1)) + ';' +
'const zcReduce2 = ' + UIntToStr(Cardinal(TZipCompression.zcReduce2)) + ';' +
'const zcReduce3 = ' + UIntToStr(Cardinal(TZipCompression.zcReduce3)) + ';' +
'const zcReduce4 = ' + UIntToStr(Cardinal(TZipCompression.zcReduce4)) + ';' +
'const zcImplode = ' + UIntToStr(Cardinal(TZipCompression.zcImplode)) + ';' +
'const zcTokenize = ' + UIntToStr(Cardinal(TZipCompression.zcTokenize)) + ';' +
'const zcDeflate = ' + UIntToStr(Cardinal(TZipCompression.zcDeflate)) + ';' +
'const zcDeflate64 = ' + UIntToStr(Cardinal(TZipCompression.zcDeflate64)) + ';' +
'const zcPKImplode = ' + UIntToStr(Cardinal(TZipCompression.zcPKImplode)) + ';' +
'const zcBZIP2 = ' + UIntToStr(Cardinal(TZipCompression.zcBZIP2)) + ';' +
'const zcLZMA = ' + UIntToStr(Cardinal(TZipCompression.zcLZMA)) + ';' +
'const zcTERSE = ' + UIntToStr(Cardinal(TZipCompression.zcTERSE)) + ';' +
'const zcLZ77 = ' + UIntToStr(Cardinal(TZipCompression.zcLZ77)) + ';' +
'const zcPPMdI1 = ' + UIntToStr(Cardinal(TZipCompression.zcPPMdI1)) + ';' +
// Object
'var DZipFile; ' +
'if (!DZipFile) ' +
' DZipFile = function() {}; ' +
// Properties
' DZipFile.prototype.__defineGetter__("comment", function() { native function dZipGetComment(); return dZipGetComment(); }); ' +
' DZipFile.prototype.__defineSetter__("comment", function(a) { native function dZipSetComment(a); if(a) dZipSetComment(a); }); ' +
' DZipFile.prototype.__defineGetter__("fileCount", function() { native function dZipGetFileCount(); return dZipGetFileCount(); }); ' +
' DZipFile.prototype.__defineGetter__("mode", function() { native function dZipGetMode(); return dZipGetMode(); }); ' +
' DZipFile.prototype.__defineGetter__("utf8Support", function() { native function dZipGetUTF8Support(); return dZipGetUTF8Support(); }); ' +
' DZipFile.prototype.__defineSetter__("utf8Support", function(a) { native function dZipSetUTF8Support(a); if(a) dZipSetUTF8Support(a); }); ' +
'(function() { ' +
// Methods
' DZipFile.prototype.fileComment = function(a) { native function dZipGetFileComment(a); return dZipGetFileComment(a); }; '+
' DZipFile.prototype.fileComment = function(a,b) { native function dZipSetFileComment(a,b); return dZipSetFileComment(a,b); }; '+
' DZipFile.prototype.fileName = function(a) { native function dZipGetFileName(a); return dZipGetFileName(a); }; '+
' DZipFile.prototype.add = function(a,b,c) { native function dZipAddFileName(a,b,c); return dZipAddFileName(a,b,c); }; '+
' DZipFile.prototype.close = function() { native function dZipClose(); return dZipClose(); }; '+
' DZipFile.prototype.extractByName = function(a,b,c) { native function dZipExtractName(a,b,c); return dZipExtractName(a,b,c); }; '+
' DZipFile.prototype.extractByIndex = function(a,b,c) { native function dZipExtractIndex(a,b,c); return dZipExtractIndex(a,b,c); }; '+
' DZipFile.prototype.extractAll = function(a) { native function dZipExtractAll(a); return dZipExtractAll(a); }; '+
' DZipFile.prototype.indexOf = function(a) { native function dZipIndexOf(a); return dZipIndexOf(a); }; '+
' DZipFile.prototype.open = function(a,b) { native function dZipOpen(a,b); return dZipOpen(a,b); }; '+
'})();';
end;
destructor TV8ZipFileObjHandler.Destroy;
begin
FZip.Free();
inherited;
end;
function TV8ZipFileObjHandler.Execute(const name: ustring; const obj: ICefv8Value; const arguments: TCefv8ValueArray; var retval: ICefv8Value; var _exception: ustring): Boolean;
begin
if (name = 'dZipGetComment') then
begin
if Assigned(FZip) then
begin
retval := TCefv8ValueRef.NewString(FZip.Comment);
Result := True;
end
else Result := false;
end
else if (name = 'dZipSetComment') then
begin
if Assigned(FZip) and (length(arguments) > 0) and arguments[0].IsString() then
begin
FComment := arguments[0].GetStringValue();
FZip.Comment := FComment;
Result := true;
end
else Result := false;
end
else if (name = 'dZipGetFileCount') then
begin
if Assigned(FZip) then
begin
retval := TCefv8ValueRef.NewInt(FZip.FileCount);
Result := True;
end
else Result := false;
end
else if (name = 'dZipGetMode') then
begin
if Assigned(FZip) then
begin
retval := TCefv8ValueRef.NewUInt(Cardinal(FZip.Mode));
Result := True;
end
else Result := false;
end
else if (name = 'dZipGetUTF8Support()') then
begin
if Assigned(FZip) then
begin
retval := TCefv8ValueRef.NewBool(FZip.UTF8Support);
Result := True;
end
else Result := false;
end
else if (name = 'dZipSetUTF8Support()') then
begin
if Assigned(FZip) and (length(arguments) > 0) and arguments[0].IsBool() then
begin
FUTF8Support := arguments[0].GetBoolValue();
FZip.UTF8Support := FUTF8Support;
Result := true;
end
else Result := false;
end
else if (name = 'dZipGetFileComment') then
begin
if Assigned(FZip) and (Length(arguments) > 0) and arguments[0].IsUInt() then
begin
retval := TCefv8ValueRef.NewString(FZip.FileComment[arguments[0].GetUIntValue()]);
Result := true;
end
else Result := false;
end
else if (name = 'dZipSetFileComment') then
begin
if Assigned(FZip) and (Length(arguments) > 1) and arguments[0].IsUInt() and arguments[1].IsString() then
begin
FZip.FileComment[arguments[0].GetUIntValue()] := arguments[1].GetStringValue();
retval := TCefv8ValueRef.NewString(FZip.FileComment[arguments[0].GetUIntValue()]);
Result := true;
end
else Result := false;
end
else if (name = 'dZipGetFileName') then
begin
if Assigned(FZip) and (Length(arguments) > 0) and arguments[0].IsUInt() then
begin
retval := TCefv8ValueRef.NewString(FZip.FileNames[arguments[0].GetUIntValue()]);
Result := true;
end
else Result := false;
end
else if (name = 'dZipAddFileName') then
begin
if Assigned(FZip) and (Length(arguments) > 2) and arguments[0].IsString() and arguments[1].IsString() and arguments[2].IsUInt() then
begin
if Length(arguments[1].GetStringValue()) = 0 then
FZip.Add(arguments[0].GetStringValue(), ExtractFileName(arguments[0].GetStringValue()), TZipCompression(arguments[2].GetUIntValue()))
else
FZip.Add(arguments[0].GetStringValue(), arguments[1].GetStringValue(), TZipCompression(arguments[2].GetUIntValue()));
Result := true;
end
else Result := false;
end
else if (name = 'dZipClose') then
begin
if Assigned(FZip) then
begin
FZip.Close();
Result := true;
end
else Result := false;
end
else if (name = 'dZipExtractName') then
begin
if Assigned(FZip) and (Length(arguments) > 2) and arguments[0].IsString() and arguments[1].IsString() and arguments[2].IsBool() then
begin
FZip.Extract(arguments[0].GetStringValue(), arguments[1].GetStringValue(), arguments[2].GetBoolValue());
Result := true;
end
else Result := false;
end
else if (name = 'dZipExtractIndex') then
begin
if Assigned(FZip) and (Length(arguments) > 2) and arguments[0].IsUInt() and arguments[1].IsString() and arguments[2].IsBool() then
begin
FZip.Extract(arguments[0].GetUintValue(), arguments[1].GetStringValue(), arguments[2].GetBoolValue());
Result := true;
end
else Result := false;
end
else if (name = 'dZipExtractAll') then
begin
if Assigned(FZip) and (Length(arguments) > 0) and arguments[0].IsString() then
begin
FZip.ExtractAll(arguments[0].GetStringValue());
Result := true;
end
else Result := false;
end
else if (name = 'dZipIndexOf') then
begin
if Assigned(FZip) and (Length(arguments) > 0) and arguments[0].IsString() then
begin
retval := TCefv8ValueRef.NewInt(FZip.IndexOf(arguments[0].GetStringValue()));
Result := true;
end
else Result := false;
end
else if (name = 'dZipOpen') then
begin
if Assigned(FZip) and (Length(arguments) > 1) and arguments[0].IsString() and arguments[1].IsUInt() then
begin
FZip.Open(arguments[0].GetStringValue(), TZipMode(arguments[1].GetUIntValue()));
Result := true;
end
else Result := false;
end
else
begin
Result := false;
end;
end;
procedure TV8ZipFileObjHandler._OnProgress(Sender: TObject; FileName: string; Header: TZipHeader; Position: Int64);
begin
//???
end;
end.
Code: Select all
{$IFDEF DELPHI12_UP}procedure{$ELSE}class procedure TJSExtensionFrm.{$ENDIF}GlobalCEFApp_OnWebKitInitializedEvent;
var
ZipFileObjHandler: ICefv8Handler;
begin
// This is the JS extension example with a function in the "JavaScript Integration" wiki page at
// https://bitbucket.org/chromiumembedded/cef/wiki/JavaScriptIntegration.md
ZipFileObjHandler := TV8ZipFileObjHandler.Create();
CefRegisterExtension('v8/DZipfile', (ZipFileObjHandler as TV8ZipFileObjHandler).ExtensionCode, ZipFileObjHandler);
end;