WebKit: Where to Change WKBrowsingContextController to Fix Trimming of HTTP Body?

Hey all,


I've been looking at WebKit for a bit and have noticed that there's an issue with intercepting requests. See ios - WKWebView and NSURLProtocol not working - Stack Overflow for a greater description of the problem, but the general gist is that the introduction of WKWebView in iOS 8, WebKit has complicated the use of NSURLProtocol, on which many large-scale projects (including mine) rely heavily. A common workaround for this is to use WKBrowsingContextController's registerSchemeForCustomProtocol method, but this route doesn't work for "http" requests, as WebKit internally trims the the bodies of custom protocols under the "http" scheme.


I've spent a few days reading through the code, but I'm still confused as to how everything interacts. I'm hoping at least one of you is familar with the files I'll be touching and can provide some guidance. As a general overview, here's how I've gathered everything works:


  • WKBrowsingContextController has a method, registerSchemeForCustomProtocol, which accepts string schemes and adds them to an encoded list of schemes to permit custom protocols. As far as I'm aware, this method isn't relevant to the "http" problem. WKBrowsingContextController is implemented at webkit/WKBrowsingContextController.mm at 989f1ffc97f6b168687cbfc6f98d35880fdd29de · WebKit/webkit · GitHub, and registerSchemeForCustomProtocol is implemented on line 104
  • WKBrowsingContextController also has a method, setUpPagePolicyClient, which handles various details relevant to a page's metadata given a WKBrowsingContextController and a WebPageProxy. This method eventually calls WKURLRequestCopyNSURLRequest several times, which accepts a request and returns a copy of the created NSURLRequest. setUpPagePolicyClient is implemented at the link provided above and is implemented on line 449. The first use of WKURLRequestCopyNSURLRequest is found on line 468
  • WKURLRequestCopyNSURLRequest is a utility of the WKURLRequestNS class, calling ResourceRequest's nsURLRequest method with HTTPBodyUpdatePolicy::DoNotUpdateHTTPBody as an argument. WKURLRequestNS is implemented at webkit/WKURLRequestNS.mm at 90e9625cdec06ffd201df5d1c9b5fa03b7c02481 · WebKit/webkit · GitHub, and WKURLRequestCopyNSURLRequest is defined on line 43. The HTTPBodyUpdatePolicy namespace also contains UpdateHTTPBody and is implemented at webkit/ResourceRequestBase.h at 2aa4be447cf29c191440778ec86490bb35c13113 · WebKit/webkit · GitHub on line 48


My intuition is that adding a property like shouldUpdateHTTPBody to WKBrowsingContextController would allow for setUpPagePolicyClient to be changed so that a conditional, which tests shouldUpdateHTTPBody, wraps around every use of WKURLRequestCopyNSURLRequest. In the event shouldUpdateHTTPBody is true, call a new utility of WKURLRequestNS, say WKURLRequestCopyNSURLRequestWithHTTPBody, which is functionally identical to the exist utility but instead passes HTTPBodyUpdatePolicy::UpdateHTTPBody as an argument.


This sounds reasonable to me, but I'm unsure as to whether this change would actually solve the "http" issue. Thoughts?

  • I am not sure I understand your use case, but for me, I simply need a way to inject a custom header into requests that are handled by a WKWebView. With NSSelectorFromString(@"registerSchemeForCustomProtocol:"), I can do that for all WebViews in my app, but it would be OK to have to set this interceptor for https scheme for each WebView separately. I really hate the idea of having to modify the HTML content of each WebView with some javascript only to replace the https scheme with some custom scheme (then, I can use the documented setURLSchemeHandler as @eskimo demonstrates in another thread).

    Any hints?

Add a Comment

Replies

What are you trying to accomplish? Are you really trying to intercept http/https requests?


In most cases, people can replace NSURLProtocol with WKURLSchemeHandler. You can't replace system schemes like http/https, but you can create your own schemes. It sounds like you are bypassing that and diving right into the lower-level WebKit. Is this for iOS? Would that be considered a private API? Wouldn't it be DOA then? Are you sure it is a good idea to spend much time on a project where Apple has this kind of daily death grip on your livelihood?

  • I simply need a way to inject a custom header into requests that are handled by a WKWebView.

    With NSSelectorFromString(@"registerSchemeForCustomProtocol:"), I can do that for all WebViews in my app, but it would be OK to have to set this interceptor for https scheme for each WebView separately. I really hate the idea of having to modify the HTML content of each WebView with some javascript only to replace the https scheme with some custom scheme (then, I can use the documented setURLSchemeHandler as @eskimo demonstrates in another thread). 

    Any hints?

Add a Comment
Is there any update on this topic? I am also interested in accomplish the same task. Should it be possible to use custom objects equals to WKBrowsingContextController, WKURLRequestNS, copying all code but adding those fixes?