1. 개요
Chromium에는 임베딩된 TWebBrowser 컴포넌트처럼 웹브라우저를 직접 핸들링하는 기능을 제공하지 않습니다. 따라서 VCL Application에서 Embedding시킨 Chromium 웹브라우저에 일을 시키려면(예를 들어 웹페이지 HTML을 얻는 등등..) Chromium의 메시징 처리 매커니즘을 이해할 필요가 있습니다.
2. Chromium 메시지 처리 개념도
3. Chromium 기본 메시지 처리 매커니즘
3.1 Chromium 어플리케이션 초기화 및 메시지 처리 핸들러 지정
Chromium을 Embedding하는 VCL 어플리케이션에는 최초 1회 다음과 같은 Chromium이 동작하는 어플리케이션이라고 초기화를 해 주어야 합니다.
GlobalCEFApp := TCefApplication.Create;
그리고 GlobalCEFApp.OnProcessMessageReceived 메시지 핸들러에서 Chromium에 전달되는 모든 이벤트를 처리 합니다. 이 이벤트 핸들러에는 TChromium 컴포넌트별로 수신된 메시지를 각각 처리할 수 있기 때문에 메시지를 수신받은 브라우저등 메타 정보를 인식할 수 있습니다. 이 이벤트 핸들러의 함수 원형은 다음과 같습니다.
procedure GlobalCEFApp_OnProcessMessageReceived(const browser : ICefBrowser; //메시지를 전달받은 브라우저(TChromium.browser) const frame : ICefFrame; //메시지를 전달받은 프레임 sourceProcess : TCefProcessId; //프로세스ID const message : ICefProcessMessage; //전달받은 메시지 var aHandled : boolean); //처리여부 결정
메시지 처리 핸들러를 다음과 같이 CEFApplication의 이벤트 핸들러로 등록해 주어야 합니다.
//어플리케이션마다 한번만 초기화 해주어야 함 GlobalCEFApp := TCefApplication.Create; GlobalCEFApp.RemoteDebuggingPort := 9000; GlobalCEFApp.OnProcessMessageReceived := GlobalCEFApp_OnProcessMessageReceived; //메시지처리 핸들러 GlobalCEFApp.DisableFeatures := 'NetworkService,OutOfBlinkCors'; GlobalCEFApp.LogFile := 'debug.log'; //Chromium내부에서 남긴 오류를 저장할 파일 GlobalCEFApp.LogSeverity := LOGSEVERITY_ERROR;//LOGSEVERITY_INFO; //저장할 오류의 종류
3.2 Chromium에 처리할 메시지 생성/전송
Chromium에서 사용되는 메시지는 TCefProcessMessageRef 클래스를 사용하여 생성후 전송합니다.
이때 TChromium에 전달할 대상은 PID_RENDERER 이어야 합니다.
//메시지 생성 TempMsg := TCefProcessMessageRef.New('HTML얻기'); //메시지 전송 Chromium1.SendProcessMessage(PID_RENDERER, TempMsg);
3.3 Chromium Application 메시지 핸들러에서 VISITDom 객체 생성 및 실행
앞서 등록한 Chromium Application 메시지 핸들러에서 message.name에 따른 각 용도별 VisitDom 객체를 생성하고 VisitDom을 호출함으로 해서 원하는 일을 웹브라우저에 시킬 수 있게 됩니다.
이때 VisitDom객체 생성시 동작할 Callback 함수를 함께 전달해 주어야 하는데 VisitDom객체 내부적으로 visit 함수가 실행 될 때 지정된 콜백함수가 실행되기 때문입니다.
VisitDom객체는 유닛 "uCEFDomVisitor.pas"에 선언된 TCefDomVisitorOwn 클래스를 상속받아 작성된 클래스를 사용할 수 있으며 이미 기정의된 두개의 TCefDomVisitorOwn 객체를 사용할 수도 있습니다.
TCefFastDomVisitor = class(TCefDomVisitorOwn) protected FProc : TCefDomVisitorProc; procedure visit(const document: ICefDomDocument); override; public constructor Create(const proc: TCefDomVisitorProc); reintroduce; virtual; end; TCefFastDomVisitor2 = class(TCefDomVisitorOwn) protected FProc : TCefDomVisitorProc2; FBrowser : ICefBrowser; FFrame : ICefFrame; procedure visit(const document: ICefDomDocument); override; public constructor Create(const browser: ICefBrowser; const frame: ICefFrame; const proc: TCefDomVisitorProc2); reintroduce; virtual; destructor Destroy; override; end;
콜백함수 타입인 "TCefDomVisitorProc" 또는 "TCefDomVisitorProc2"는 "uCEFInterfaces.pas"유닛에 다음과 같이 정의되어 있는데 이 함수 타입을 별도로 정의하여 사용할 수도 있습니다.
unit uCEFInterfaces; ... TCefDomVisitorProc = {$IFDEF DELPHI12_UP}reference to{$ENDIF} procedure(const document: ICefDomDocument); TCefDomVisitorProc2 = {$IFDEF DELPHI12_UP}reference to{$ENDIF} procedure(const browser : ICefBrowser; const frame: ICefFrame; const document: ICefDomDocument);
어플리케이션 이벤트 핸들러에서 메시지명에 따라 다음과 같이 VisitDOM을 호출할 수 있습니다
// HTML을 얻는 Visitor 콜백함수 procedure DOMVisitor_GETHTML(const browser: ICefBrowser; const frame: ICefFrame; const document: ICefDomDocument); var msg: ICefProcessMessage; begin // 이 메시지는 TChromium.OnProcessMessageReceived 이벤트 핸들러에서 받을 수 있다. msg := TCefProcessMessageRef.New(DOMVISITOR_MSGNAME_FULL); msg.ArgumentList.SetString(0, document.Body.AsMarkup); frame.SendProcessMessage(PID_BROWSER, msg); //처리 결과를 웹브라우저(PID_BROWSER)로 보낸다. end; // TEXT를 얻는 Visitor 콜백함수 procedure DOMVisitor_GETTEXT(const browser: ICefBrowser; const frame: ICefFrame; const document: ICefDomDocument); var msg: ICefProcessMessage; begin // 이 메시지는 TChromium.OnProcessMessageReceived 이벤트 핸들러에서 받을 수 있다. msg := TCefProcessMessageRef.New(DOMVISITOR_MSGNAME_FULL); msg.ArgumentList.SetString(0, document.Body.AsText); frame.SendProcessMessage(PID_BROWSER, msg); //처리 결과를 웹브라우저(PID_BROWSER)로 보낸다. end; procedure GlobalCEFApp_OnProcessMessageReceived(const browser : ICefBrowser; //메시지를 전달받은 브라우저(TChromium.browser) const frame : ICefFrame; //메시지를 전달받은 프레임 sourceProcess : TCefProcessId; //프로세스ID const message : ICefProcessMessage; //전달받은 메시지 var aHandled : boolean); //처리여부 결정 begin aHandled := False; if (browser <> nil) then begin if (message.name = 'HTML얻기') then begin TempFrame := browser.MainFrame; if (TempFrame <> nil) then begin TempVisitor := TCefFastDomVisitor2.Create(browser, TempFrame, DOMVisitor_GETHTML); TempFrame.VisitDom(TempVisitor); end; aHandled := True; end else if (message.name = 'TEXT얻기') then begin TempFrame := browser.MainFrame; if (TempFrame <> nil) then begin TempVisitor := TCefFastDomVisitor2.Create(browser, TempFrame, DOMVisitor_GETTEXT); TempFrame.VisitDom(TempVisitor); end; aHandled := True; end else ....
3.4 VisitDOM 처리 결과 받기
VisitDOM콜백 함수에 의해 실행된 결과 메시지를 보냈다면 TChromium.OnProcessMessageReceived 핸들러에서 메시지를 받을 수 있습니다.
procedure TDOMVisitorFrm.Chromium1ProcessMessageReceived(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; sourceProcess: TCefProcessId; const message: ICefProcessMessage; out Result: Boolean); begin Result := False; if (message = nil) or (message.ArgumentList = nil) then exit; if (message.Name = DOMVISITOR_MSGNAME_GETHTML) then begin ShowStatusText('DOM Visitor result text : ' + message.ArgumentList.GetString(0)); Result := True; end else if (message.Name = DOMVISITOR_MSGNAME_GETTEXT) then begin ShowStatusText('DOM Visitor result text : ' + message.ArgumentList.GetString(0)); Result := True; end .... end;
'프로그래밍 > Chromium(CEF4Delphi)' 카테고리의 다른 글
[Chromium] CEF4Delphi - RTTI를 이용한 JavaScript 실행 및 결과 처리 (0) | 2019.10.30 |
---|---|
[Chromium] CEF4Delphi - Context Menu추가 구현하기 (0) | 2019.10.29 |
[Chromium] CEF4Delphi - 자바스크립트로 델파이 코드 실행 (0) | 2019.09.30 |
[Chromium] CEF4Delphi - 크롬브라우저 팝업메뉴 추가 및 실행 (0) | 2019.09.25 |
[Chromium] CEF4Delphi - Javascript 유효성 체크(Evaluate Javascript) (0) | 2019.09.19 |