Repo (3.1750.1738)에서 최신 Delphi Chromium Embedded 코드를 사용하여 CEF1 프로젝트를 CEF3으로 변환 할 때 몇 가지 문제가 있습니다. 간단히 말해서, 나는 내가 등록 할 확장 프로그램을 사용했습니다. 그런 다음 html 쪽에서는 기본 호출을 사용하여 javascript 객체를 Delphi 호스트에 등록합니다. 나중에 호출 할 수 있도록 객체와 객체의 컨텍스트를 저장합니다. 그러나 이것은 DCEF3에서 작동하지 않는 것 같습니다. 나는 물건을 얻을 수 있고 그것은 맥락이다. 그러나 나중에 context.Enter
으로 전화하면 실패합니다. 이것이 cef1과 cef3 사이의 아키텍처 변화와 관련이 있는지 궁금합니다. 나는 이미 확장을 조금 변경하여 OnWebkitIniitalized
에 등록해야했습니다.Context.Enter가 CEF3에서 항상 실패합니다.
unit MainUnit;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, cefvcl, ceflib, StdCtrls;
type
TMainForm = class(TForm)
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
Guest: ICefv8Value;
GuestContext: ICefv8Context;
Browser: TChromium;
procedure BrowserConsoleMessage(Sender: TObject; const browser: ICefBrowser;
const message, source: ustring; line: Integer; out Result: Boolean);
public
function ExtensionExecute(const name: ustring; const obj: ICefv8Value;
const arguments: TCefv8ValueArray; var retval: ICefv8Value;
var exception: ustring): Boolean;
end;
var
MainForm: TMainForm;
BrowserExt: TCefv8HandlerOwn;
implementation
{$R *.dfm}
const
code =
'var cef;'+
'if (!cef)'+
' cef = {};'+
'if (!cef.nes)'+
' cef.nes = {};'+
'(function() {'+
' cef.nes.callNative = function() {'+
' native function callNative();'+
' return callNative.apply(this, arguments);'+
' };'+
'})();';
type
TCustomRenderProcessHandler = class(TCefRenderProcessHandlerOwn)
protected
procedure OnWebKitInitialized; override;
end;
TExtension = class(TCefv8HandlerOwn)
protected
function Execute(const name: ustring; const obj: ICefv8Value;
const arguments: TCefv8ValueArray; var retval: ICefv8Value;
var exception: ustring): Boolean; override;
public
Host: TMainForm;
end;
function TExtension.Execute(const name: ustring; const obj: ICefv8Value;
const arguments: TCefv8ValueArray; var retval: ICefv8Value;
var exception: ustring): Boolean;
begin
Result := Host.ExtensionExecute(name, obj, arguments, retval, exception);
end;
procedure TMainForm.Button1Click(Sender: TObject);
var
o: ICefv8Value;
begin
if GuestContext.Enter then
begin
o := Guest.GetValueByKey('foo');
OutputDebugString(PChar('foo found now: ' + BoolToStr(Assigned(o), True)));
GuestContext.Exit;
end
else
OutputDebugString('GuestContext.Enter failed');
end;
function TMainForm.ExtensionExecute(const name: ustring; const obj: ICefv8Value;
const arguments: TCefv8ValueArray; var retval: ICefv8Value;
var exception: ustring): Boolean;
var
o: ICefv8Value;
begin
OutputDebugStringW(PWideChar('Execute: ' + name));
if name = 'callNative' then
begin
GuestContext := TCefv8ContextRef.Current;
Guest := arguments[0];
o := Guest.GetValueByKey('foo');
OutputDebugString(PChar('foo found: ' + BoolToStr(Assigned(o), True)));
end;
Result := True;
end;
procedure TMainForm.FormCreate(Sender: TObject);
begin
Browser := TChromium.Create(Self);
Browser.Options.JavascriptDomPaste := STATE_DISABLED;
Browser.Options.CaretBrowsing := STATE_DISABLED;
Browser.OnConsoleMessage := BrowserConsoleMessage;
Browser.Color := clWhite;
Browser.Align := alClient;
Browser.DefaultUrl := 'http://localhost/test2/home.html';
Browser.Parent := Self;
BrowserExt := TExtension.Create;
TExtension(BrowserExt).Host := Self;
Browser.Load(Browser.DefaultUrl);
end;
procedure TMainForm.BrowserConsoleMessage(Sender: TObject;
const browser: ICefBrowser; const message, source: ustring; line: Integer;
out Result: Boolean);
begin
OutputDebugStringW(PWideChar('[line ' + IntToStr(Line) + '] ' + message));
end;
{ TCustomRenderProcessHandler }
procedure TCustomRenderProcessHandler.OnWebKitInitialized;
begin
inherited;
CefRegisterExtension('v8/nes', code, BrowserExt as ICefV8Handler);
end;
initialization
CefRemoteDebuggingPort := 9000;
CefRenderProcessHandler := TCustomRenderProcessHandler.Create;
CefBrowserProcessHandler := TCefBrowserProcessHandlerOwn.Create;
end.
그리고 자바 스크립트 코드 :
console.log('startup');
var guest = {foo:function() {
console.log('foo called');
return 42;
}};
if (typeof(cef) !== "undefined") {
console.log('registering guest');
cef.nes.callNative(guest);
}
else {
console.log('no cef');
}
console.log('startup done');
TMainForm.ExtensionExecute
가 트리거되고 callNative이 발생
여기 내 코드입니다. 하지만 나중에 Button1Click을 할 때, 컨텍스트 입력은 항상 False를 반환합니다.
또한 Button1에서 Browser.Browser.MainFrame.Getv8Context를 확인하면 nil을 얻습니다. DCEF1에서 동일한 것을 시도 할 때 유효한 컨텍스트를 얻습니다. – jep
또한 이것을 테스트하기 위해 단일 프로세스 모드를 사용하고 있음을 지적 할 가치가 있습니다. – jep