2016-09-11 93 views
3

我想实现一个fpcef3渲染进程处理程序作为子:如何FreePascal的执行/拉撒路一个cef3渲染进程处理程序在子进程

以下设在fpcef3 github repo的例子中,我已成功地创建渲染过程的处理程序的子过程:

Program subprocess; 

{$mode objfpc}{$H+} 

Uses 
    {$IFDEF UNIX}{$IFDEF UseCThreads} 
    cthreads, 
    {$ENDIF}{$ENDIF} 
    cef3lib, cef3types, cef3api, Handler; 

Var 
    Args : TCefMainArgs; 

begin 
    CefLoadLibrary; 
    CefRenderProcessHandler := TCustomRenderProcessHandler.Create; 

    {$IFDEF WINDOWS} 
    Args.instance := HINSTANCE(); 

    Halt(cef_execute_process(@Args, nil, nil)); 
    {$ELSE} 
    Args.argc := argc; 
    Args.argv := argv; 

    Halt(cef_execute_process(@Args, nil, nil)); 
    {$ENDIF} 
end. 

TCustomRenderProcessHandler是相同的设置有在实施例中的JavaScript示例处理程序子目录:

Unit Handler; 

{$MODE objfpc}{$H+} 

(* 
* Everything in here is called from a render process, so there is no access to GUI and all the 
* data of the main process. 
*) 

Interface 

Uses 
    Classes, SysUtils, 
    cef3types, cef3intf, cef3ref, cef3own, cef3lib; 

Type 
    { Custom handler for the render process } 
    TCustomRenderProcessHandler = class(TCefRenderProcessHandlerOwn) 
    protected 
    // Test Window Bindings 
    procedure OnContextCreated(const browser: ICefBrowser; const frame: ICefFrame; const context: ICefv8Context); override; 
    // Test Extension 
    procedure OnWebKitInitialized; override; 
    end; 

    TMyHandler = class(TCefv8HandlerOwn) 
    protected 
    function Execute(const name: ustring; const obj: ICefv8Value; 
    const arguments: ICefv8ValueArray; var retval: ICefv8Value; 
    var exception: ustring): Boolean; override; 
    end; 

Implementation 

Var 
    mystr : String; 

{ TMyHandler } 

function TMyHandler.Execute(const name : ustring; const obj : ICefv8Value; 
    const arguments : ICefv8ValueArray; var retval : ICefv8Value; 
    var exception : ustring) : Boolean; 
begin 
    // return a value 
    //retval := TCefv8ValueRef.NewString('TMyHandler'); 
    retval := TCefv8ValueRef.NewDate(Now); 

    Result := True; 
end; 

{ TCustomRenderProcessHandler } 

procedure TCustomRenderProcessHandler.OnContextCreated(const browser : ICefBrowser; 
    const frame : ICefFrame; const context : ICefv8Context); 
Var 
    myWin : ICefv8Value; 
    args : ICefv8ValueArray; 
begin 
    myWin := context.GetGlobal; 
    mystr := 'a test string'; 
    SetLength(args, 1); 
    args[0] := TCefv8ValueRef.NewString(mystr); 
    myWin.SetValueByKey('myval', args[0], []); 
end; 

procedure TCustomRenderProcessHandler.OnWebKitInitialized; 
Var 
    Code: ustring; 
begin 
    Code := 
    'var cef;'+ 
    'if (!cef)'+ 
    ' cef = {};'+ 
    'if (!cef.test)'+ 
    ' cef.test = {};'+ 
    '(function() {'+ 
    ' cef.test.__defineGetter__(''test_param'', function() {'+ 
    ' native function GetTestParam();'+ 
    ' return GetTestParam();'+ 
    ' });'+ 
    ' cef.test.__defineSetter__(''test_param'', function(b) {'+ 
    ' native function SetTestParam();'+ 
    ' if(b) SetTestParam(b);'+ 
    ' });'+ 
    ' cef.test.test_object = function() {'+ 
    ' native function GetTestObject();'+ 
    ' return GetTestObject();'+ 
    ' };'+ 
    '})();'; 

    CefRegisterExtension('example/v8', Code, TMyHandler.Create as ICefv8Handler); 
end; 

end. 

最后,在我的主进程的主要形式,我提供的路径子:

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    CefSingleProcess := False; 

    //CefRenderProcessHandler := TCustomRenderProcessHandler.Create; 
    CefBrowserSubprocessPath := 'C:\Users\aludin\fpCEF3-master\Examples\SubProcess\subprocess64.exe' 
end;  

当我启动了主要的应用程序,显示正确的Chromium浏览器,但处理程序不会被调用(不过,我可以看到子进程已启动)。初始化处理程序时我做错了什么?

感谢您的帮助!

+0

@MartynA所以我检查了两个项目,他们都编译为64位Windows exes。我也使用特定的64位CEF3。我还没有检查过,如果这是32位工作,但建设64位exes应该不是一个问题(因为主进程管理成功加载CEF3并显示浏览器视图) – BigONotation

+0

@MartynAndual其实感谢您的建议!我会尝试附加到子进程...但不知何故,我有一种感觉,渲染进程处理程序根本不会初始化... – BigONotation

+0

尝试附加到子进程,并按预期方式执行渲染的方法处理程序从不被调用。我怀疑主进程不“看到”子进程渲染处理程序...因此,在子进程 – BigONotation

回答

2

好了,终于搞清楚了,我觉得在花了这么多时间之后在这里添加了几个诅咒词。

在fpcef3源代码中进行了一点挖掘并单步执行主进程之后,我意识到需要创建一个ICefApp应用程序实例并将自定义渲染进程处理程序分配给此应用程序。所以为了简化我的生活并避免实现ICefApp接口,我“劫持”了在主流程中内部使用的类。更新后的子进程的实现,现在是由下面的代码给出:

Program subprocess; 

{$mode objfpc}{$H+} 

Uses 
    {$IFDEF UNIX}{$IFDEF UseCThreads} 
    cthreads, 
    {$ENDIF}{$ENDIF} 
    cef3lib, cef3types, cef3api, cef3own, cef3intf, Handler; 

Var 
    Args : TCefMainArgs; 
    app : ICefApp; 

begin 
    CefLoadLibrary; 
    CefRenderProcessHandler := TCustomRenderProcessHandler.Create; 
    app := TInternalApp.Create; 
    {$IFDEF WINDOWS} 
    Args.instance := HINSTANCE(); 

    Halt(cef_execute_process(@Args, CefGetData(app), nil)); 
    {$ELSE} 
    Args.argc := argc; 
    Args.argv := argv; 

    Halt(cef_execute_process(@Args, CefGetData(app), nil)); 
    {$ENDIF} 
end. 

现在ICefApp实例将使用分配给CefRenderProcessHandler渲染进程处理程序。最后注意cef_execute_process()已被修改为将该应用程序作为附加参数。

+0

很高兴你知道了,+1 – MartynA

+0

嗨,我自己想出了这个问题。你的解决方案似乎工作正常。但是你能否解释我们应该怎样做呢?创建一个'ICefApp',分配自定义处理程序等...? – Vassilis

+0

@VassilisGr对不起,我不明白你的问题?相反,你是什么意思? – BigONotation