2015-02-03 2 views
1

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를 반환합니다.

+0

또한 Button1에서 Browser.Browser.MainFrame.Getv8Context를 확인하면 nil을 얻습니다. DCEF1에서 동일한 것을 시도 할 때 유효한 컨텍스트를 얻습니다. – jep

+0

또한 이것을 테스트하기 위해 단일 프로세스 모드를 사용하고 있음을 지적 할 가치가 있습니다. – jep

답변

1

이것은 다중 스레드/프로세스로 변경되는 CEF3 아키텍처 때문입니다. 더 이상 코드를 직접 호출 할 수는 없지만 Browser.SendProcessMessage를 사용하여 메시지를 앞뒤로 전달하고 OnProcessMessage 처리기로 처리해야합니다.

관련 문제