본문 바로가기

프로그래밍/Chromium(CEF4Delphi)

[Chromium] CEF4Delphi - 자바스크립트로 델파이 코드 실행

1. 개요

  •  CEF는 델파이 Client Application에서 사용 가능한 JS Type, Array, Function, Extensions, Object 등등 JS의 특성을 제공
  •  가장 큰 특징은 자바스크립트에서 델파이 코드를 실행시킬 수 있음

Chromium Message Architecture

 

2. 처리 Process

  •    TChromium.ExecuteJavascript로 사용자 정의 JavaScript Code 실행
  •    사용자 정의 JavaScript Code는 Chromium의 Renderer Process에서 실행 되고 사용자가 정의한 확장된 JavaScript를 호출하여 실행 시킨다. 이때 델파이 코드도 Renderer Process내에서 실행
  •    사용자 정의 Javascript에 포함된 Delphi코드는 Browser Process에 처리 결과 등의 전달을 위해서 ICefFrame.SendProcessMessage를 사용하여 전달
  •    Browser Process는 이 정보를 TChromium.OnProcessMessageReceived 이벤트로 전달 받는다.

 

3. 자바 확장 객체(Javascript Extension)

  자바확장 객체는 TCefv8HandlerOwn을 상속받은 개체로 생성 해야 하고, TCefv8HandlerOwn의 Execute 함수를 Override해서 사용 해야 함.

  자바확장 객체를 사용하기 위해서는 GlobalCEFApp.OnWebKitInitialized 이벤트에 등록 해야 함.

 


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

...
  
function TTestExtensionHandler.Execute(const name      : ustring;
                                       const obj       : ICefv8Value;
                                       const arguments : TCefv8ValueArray;
                                       var   retval    : ICefv8Value;
                                       var   exception : ustring): Boolean;
var
  msg: ICefProcessMessage;
begin
  if (name = 'mouseover') then
    begin
      if (length(arguments) > 0) and arguments[0].IsString then
        begin
          msg := TCefProcessMessageRef.New(MOUSEOVER_MESSAGE_NAME);
          msg.ArgumentList.SetString(0, arguments[0].GetStringValue);

          TCefv8ContextRef.Current.Browser.MainFrame.SendProcessMessage(PID_BROWSER, msg);
        end;

      Result := True;
    end
   else
    if (name = 'sendresulttobrowser') then
      begin
        if (length(arguments) > 1) and arguments[0].IsString and arguments[1].IsString then
          begin
            msg := TCefProcessMessageRef.New(arguments[1].GetStringValue);
            msg.ArgumentList.SetString(0, arguments[0].GetStringValue);

            TCefv8ContextRef.Current.Browser.MainFrame.SendProcessMessage(PID_BROWSER, msg);
          end;

        Result := True;
      end
     else
      Result := False;
end;

.....
// 초기화 코드 함수 작성
procedure GlobalCEFApp_OnWebKitInitialized;
var
  TempExtensionCode : string;
  TempHandler       : ICefv8Handler;
begin
  // 참고 문서
  // https://bitbucket.org/chromiumembedded/cef/wiki/JavaScriptIntegration.md

  TempExtensionCode := 'var myextension;' +
                       'if (!myextension)' +
                       '  myextension = {};' +
                       '(function() {' +
                       '  myextension.mouseover = function(a) {' +
                       '    native function mouseover();' +
                       '    mouseover(a);' +
                       '  };' +
                       '  myextension.sendresulttobrowser = function(b,c) {' +
                       '    native function sendresulttobrowser();' +
                       '    sendresulttobrowser(b,c);' +
                       '  };' +
                       '})();';

  try
    TempHandler := TTestExtensionHandler.Create;
    CefRegisterExtension('myextension', TempExtensionCode, TempHandler);
  finally
    TempHandler := nil;
  end;
end;

//GlobalCEFApp초기화시 GlobalCEFApp.OnWebKitInitialized에 등록
procedure CreateGlobalCEFApp;
begin
  GlobalCEFApp                     := TCefApplication.Create;
  GlobalCEFApp.OnWebKitInitialized := GlobalCEFApp_OnWebKitInitialized;
  GlobalCEFApp.DisableFeatures     := 'NetworkService,OutOfBlinkCors';

  {$IFDEF INTFLOG}
  GlobalCEFApp.LogFile             := 'debug.log';
  GlobalCEFApp.LogSeverity         := LOGSEVERITY_INFO;
end;

4. Extensioncode JavaScript)

var myextension;
if (!myextension)
	myextension = {};
(function() {
    myextension.mouseover = function(a) {
        native function mouseover();
        mouseover(a);
    };                       
    myextension.sendresulttobrowser = function(b,c) {
        native function sendresulttobrowser();
        sendresulttobrowser(b,c);
    };
 }
)();