How can I return custom content for specific URLs requested by a Windows Runtime WebView?

Raymond

If you’re using a Windows Runtime WebView control, you may want to return custom content when the page requests content from specific URIs.

One scenario for this is that you want to block specific sites.

Another scenario is that you have copied the contents of a site locally, and you want all intra-site navigations to be served from your local copy. This is a handy way of converting a Web-based site into an app that can run offline.

Yet another scenario is that the site and your app are in cahoots, and the site makes queries to specific URIs, knowing that your app will intercept the request and inject custom results.

Whatever the scenario, you can do this by using the Web­Resource­Requested event. Start with the WebView sample and make these changes:

using Windows.Web.Http;

    public Scenario2_NavToString()
    {
        this.InitializeComponent();
        WebViewControl.WebResourceRequested += OnResourceRequested;
    }

    Uri fakeUri = new Uri("http://example.com/fakeme");

    void OnResourceRequested(WebView sender,
             WebViewWebResourceRequestedEventArgs e)
    {
        if (e.Request.RequestUri == fakeUri)
        {
            var response = new HttpResponseMessage(HttpStatusCode.Ok);
            response.Content = new HttpStringContent("Here is some fake content");
            e.Response = response;
        }
    }

And edit the html/html_example.html file to contain this:

<!DOCTYPE html>
<html>
    <button id=tryme>Try me</button><div id=result></div>
    <script>
tryme.addEventListener('click', function(e) {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'http://example.com/fakeme', true);
    xhr.onreadystatechange = function() {
        if (xhr.readyState == XMLHttpRequest.DONE) {
            result.innerText = `status: ${xhr.status}, content = ${xhr.responseText}`;
        }
    };
    xhr.send();
});
</script>
</html>

We change the web page content so it issues an XMLHttpRequest to the fake site http://example.com/fakeme and prints the result.

On the app side, we respond to the Web­Resource­Requested event by seeing if the request is for our custom fake site. If so, then we construct a custom response that is consists of a string of fake content. (If not, then the event handler does nothing, and the request goes out over the wire.)

3 comments

Comments are closed. Login to edit/delete your existing comments

  • Marcel Kilgus

    That’s sounds like an interesting way to catch the callback during an OAuth2 authentication cycle in desktop applications. Pity it doesn’t seem usable from native code, I recently implemented a small HTTP server in C to do exactly this (with MSHTML as an invisible browser component). Might revisit it once WebView2 becomes widely available.

    • Adam Rosenfield

      I’ve used a custom URL protocol handler for similar in the past. When starting the authentication workflow, the program will install the custom URL protocol handler into the registry (Admin not needed when installing for just the current user under HKCU) to launch the program with a certain set of command line arguments. Then it will launch the user’s default browser to the web URL needed to authenticate with a callback URL of something like myprogram://authenticate . After the user successfully authenticates, their web browser will open something like myprogram://authenticate/?token=foo , which will launch myprogram.exe -authenticate foo. Then the new process can parse the command line arguments and pass the token back to the original process via a named pipe and exit.

      • Marcel Kilgus

        That’s also an interesting approach and alleviates the problem that the return URL must allow a random port for localhost (a no-go for other IPs). The existing OAuth2 library our server guys were using had a provision for this but that was apparently broken, so they rewrote it for me. Still leaves the feeling that desktop apps are becoming second-class citizens these days, when looking for native OAuth2 client solutions I found many questions but hardly any answers.