최근 포토로그


Windows Store App의 WebView에서 alert 가로채기

이미 Server Side에 구축되어 있는 Web Page를 Store App에서 재활용 하기 위해서 가장 손쉽게 사용할 수 있는 방법은 아마도 WebView를 활용하는 것이 아닐까 한다. 

물론 WebView control이 Internet Explorer와 많은 부분을 공유하긴 하지만 HTML5에 대한 처리 매커니즘이나 일부 script 기능이 원할히 동작하지 않기 때문에(혹은 의도적으로 제약하였기 때문에) Web Page를 WebView control에 맞추어 수정할 수 없는 상황에서는 어려움에 봉착하게 된다.

가장 흔히 접하는 문제는 web page 내에서 alert와 같은 함수를 사용하는 경우인데, WebView Contol의 경우 의도적으로 alert를 사용하지 못하도록 제한하고 있다. 

Web Page를 수정할 수 있는 경우라면 Store App 전용의 Web Page를 구성하거나, 혹은 Web Page에 접속하는 클라이언트의 정보를 근간으로 Store App에 적합하게 수정된 페이지를 내려 줄 수 있겠으나, Web Page를 수정할 수 없는 경우라면 다음과 같이 alert  함수를 재정의하는 방법도 괜찮아 보인다.


구현 방식은 매우 간단하다.


1. WebView의 NavigationCompleted Event Handler를 다음과 같이 구성한다.


private async void webView_NavigationCompleted(WebView sender, WebViewNavigationCompletedEventArgs args)
{
    string result = await webView.InvokeScriptAsync("eval", new string[] { "window.alert = function (alertMessage) { window.external.notify(alertMessage) };" });
}


2. WebView의 ScriptNotify Event Handler를 다음과 같이 구성한다.


private async void webView_ScriptNotify(object sender, NotifyEventArgs e)
{
    Windows.UI.Popups.MessageDialog msgDialog = new Windows.UI.Popups.MessageDialog(e.Value);
    await msgDialog.ShowAsync();
}


간단히 설명을 더하면 Page Load가 완료되면,  eval function을 이용하여 window.alert를 window.external.notify() 함수를 호출하도록 재정의한다. 이 함수가 호출되면, WebView의 ScriptNotify event가 raise 되므로, 이 때 e.Value를 통해 전달된 메시지를 Windows.UI.Popup.MessageDialog를 이용하여 화면에 출력하는 것이다.


이러한 기법을 Script Injection이라고 하는데, 원칙적인 해결책은 아니지만, 다른 방법이 없을 경우 대안으로 고려해봄직 한것으로 생각된다.


(위 코드에서 async/await의 사용방법에는 논란이 있을 수 있다. 비동기 함수로 부터 반환값을 받을 필요가 없거나, 작업의 완료를 대기할 필요가 없는 경우라면 이 처럼 async/await를 이용하여 state machine을 내부적으로 구현하도록 허용하는 것은 그리 좋은 방법이 아니다. 하지만 설명의 초점을 흐리지 않기 위해서 이에 대한 대응 코드는 의도적으로 제외 하였다.)


덧글

댓글 입력 영역


facebook 프로필 위젯

트위터 위젯