Windows2020. 4. 27. 16:20

CEF javascript 연동

.NET에서는 다음과 같이 자바스크립트 메서드를 호출한다.

browser.ExecuteScriptAsync("document.body.style.background = 'red';");

browser.ExecuteJavaScriptAsync("(function(){ document.getElementsByName('q')[0].value = 'CefSharp Was Here!'; document.getElementsByName('btnK')[0].click(); })();");

여러개의 프래임으로 구성된 경우 임의 프레임의 스크립트를 다음과 같이 호출 한다.

browser.GetBrowser().GetFrame("SubFrame").ExecuteJavaScriptAsync("document.body.style.background = 'red';");


그럼 언제 자바스크립트를 호출할 수 있는가?

자바스크립트는 V8Context에서만 호출할 수 있다.
IRenderProcessMessageHandler의 OnContextCreated와 OnContextReleased 가 자바스크립트가 호출될 수 있는 환경의 범위를 제공한다. 각 프레임별로 호출되며 frame.IsMain으로 메인프레임여부를 판가름할 수 있다.

OnFrameLoadStart에서 DOM에 접근할 수 있으며 로딩이 완료되기 던에 DOM의 스크립트를 실행할 수 있다.

browser.RenderProcessMessageHandler = new RenderProcessMessageHandler();

public class RenderProcessMessageHandler : IRenderProcessMessageHandler {

  // Wait for the underlying JavaScript Context to be created. This is only called for the main frame.
  // If the page has no JavaScript, no context will be created.
  void IRenderProcessMessageHandler.OnContextCreated(IWebBrowser browserControl, IBrowser browser, IFrame frame)
  {
    const string script = "document.addEventListener('DOMContentLoaded', function(){ alert('DomLoaded'); });";

    frame.ExecuteJavaScriptAsync(script);
  }
}

//Wait for the page to finish loading (all resources will have been loaded, rendering is likely still happening)
browser.LoadingStateChanged += (sender, args) =>
{
  //Wait for the Page to finish loading
  if (args.IsLoading == false)
  {
    browser.ExecuteJavaScriptAsync("alert('All Resources Have Loaded');");
  }
}

//Wait for the MainFrame to finish loading
browser.FrameLoadEnd += (sender, args) =>
{
  //Wait for the MainFrame to finish loading
  if(args.Frame.IsMain)
  {
    args.Frame.ExecuteJavaScriptAsync("alert('MainFrame finished loading');");
  }
};

* 스크립트는 프레임레벨에서 수행되고 모든 페이지는 한개 이상의 프레임으로 구성된다.
* IWebBrowser.ExecuteScriptAsync 확장메서드는 하위호환성을 위해 남겨 있으며 main frame에서 js를 수행하는 숏컷처럼 사용가능하다.
* frame이 자바스크립트를 포함하지 않으면 V8Context가 생성되지 않는다.
* frame이 로드된 후 context가 없는 경우 IFrame.ExecuteJavaScriptAsync를 호출하여 V8Context을 생성할 수 있다.
* OnFrameLoadStart가 호출될때 DOM 로딩이 완료되지 않는다.
* IRenderProcessMessageHandler.OnContextCreated/OnContextReleased는 메인프레임에서만 호출된다.

결과를 리턴하는 자바스크립트 메서드의 호출은 ?

//An extension method that evaluates JavaScript against the main frame.
Task response = await browser.EvaluateScriptAsync(script);
//Evaluate javascript directly against a frame
Task response = await frame.EvaluateScriptAsync(script);

자바스크립트는 비동기로 수행되기 때문에 에러메세지, 결과, 성공플래그등을 포함하는 Task를 반환한다. 
자바스크립트가 수행될때 기본적으로 알아야 할 사항은 다음과 같다.

* 언제 호출하는게 가능한지에 대해 알아야 하며 위에서 설명하였다.
* 프레임레벨에서 스크립트가 수행되고 모든 페이지는 하나이상의 프레임으로 구성된다.
* 스크립트는 렌더프로세스내에서 수행되고 성능상의 이유로 IPC를 통해 전달되고 데이터만 반환한다.
* 프리미티브 타입인 int, double, date, bool과 string이 제공된다.
* 결과로 객체가 제공되고 IDictionary<string, object>형태로 접근을 더 용이하게하기 위해 dynamic 키워드가 제공된다.
* 프리미티브타입이나 앞서 얘기한 객체가 IList

<script type="text/javascript">

(async function() {

  await CefSharp.BindObjectAsync("boundAsync");

  // 

  boundAsync.add(16, 5).then(function (actualResult) {

    const expectedResult = 21;

    assert.equal(expectedResult, actualResult, "Add 16 + 5 resulte in " + expectedResult);

  });

})();

</script>

 

CefSharp.BindObjectAsync가 호출되면 JavascriptObjectRepository가 주어진 이름으로 인스턴스가 등록되어 있는지 확인한다. 만일 등록이 안되어 있다면 ResolveObject이벤트가 발생한다. 파라메터 없이 CefSharp.BindObjectAsync가 호출되면 등록된 경우 바운드가 되고 등록이 안되었으면 ObjectName을 All로 설정하여 ResolveObject가 모두 호출된다.

example) https://github.com/cefsharp/CefSharp.MinimalExample/tree/demo/javascriptbinding

 

 

Posted by 삼스

댓글을 달아 주세요

  1. 이전 댓글 더보기
  2. e

    2020.06.17 18:21 [ ADDR : EDIT/ DEL : REPLY ]
  3. e

    2020.06.17 18:21 [ ADDR : EDIT/ DEL : REPLY ]
  4. e

    2020.06.17 18:21 [ ADDR : EDIT/ DEL : REPLY ]
  5. e

    2020.06.17 18:21 [ ADDR : EDIT/ DEL : REPLY ]
  6. e

    2020.06.17 18:22 [ ADDR : EDIT/ DEL : REPLY ]
  7. e

    2020.06.17 18:22 [ ADDR : EDIT/ DEL : REPLY ]
  8. e

    2020.06.17 18:22 [ ADDR : EDIT/ DEL : REPLY ]
  9. e

    2020.06.17 18:22 [ ADDR : EDIT/ DEL : REPLY ]
  10. e

    2020.06.17 18:22 [ ADDR : EDIT/ DEL : REPLY ]
  11. e

    2020.06.17 18:22 [ ADDR : EDIT/ DEL : REPLY ]
  12. e

    2020.06.17 18:22 [ ADDR : EDIT/ DEL : REPLY ]
  13. e

    2020.06.17 18:22 [ ADDR : EDIT/ DEL : REPLY ]
  14. e

    2020.06.17 18:22 [ ADDR : EDIT/ DEL : REPLY ]
  15. e

    2020.06.17 18:22 [ ADDR : EDIT/ DEL : REPLY ]
  16. e

    2020.06.17 18:22 [ ADDR : EDIT/ DEL : REPLY ]
  17. e

    2020.06.17 18:22 [ ADDR : EDIT/ DEL : REPLY ]
  18. e

    2020.06.17 18:22 [ ADDR : EDIT/ DEL : REPLY ]
  19. e

    2020.06.17 18:22 [ ADDR : EDIT/ DEL : REPLY ]
  20. e

    2020.06.17 18:22 [ ADDR : EDIT/ DEL : REPLY ]
  21. e

    2020.06.17 18:22 [ ADDR : EDIT/ DEL : REPLY ]