How to Monitor Requests on Wkwebview

How can i monitor requests on WKWebview?

Finally I solved it

Since I don't have control over the web view content, I injected to the WKWebview a java script that include a jQuery AJAX request listener.

When the listener catches a request it sends the native app the request body in the method:

webkit.messageHandlers.callbackHandler.postMessage(data);

The native app catches the message in a delegate called:

(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message

and perform the corresponding actions

here is the relevant code:

ajaxHandler.js -

//Every time an Ajax call is being invoked the listener will recognize it and  will call the native app with the request details

$( document ).ajaxSend(function( event, request, settings ) {
callNativeApp (settings.data);
});

function callNativeApp (data) {
try {
webkit.messageHandlers.callbackHandler.postMessage(data);
}
catch(err) {
console.log('The native context does not exist yet');
}
}

My ViewController delegate are:

@interface BrowserViewController : UIViewController <UIWebViewDelegate, WKUIDelegate, WKNavigationDelegate, WKScriptMessageHandler, UIWebViewDelegate>

And in my viewDidLoad(), I'm creating a WKWebView:

WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc]init];
[self addUserScriptToUserContentController:configuration.userContentController];
appWebView = [[WKWebView alloc]initWithFrame:self.view.frame configuration:configuration];
appWebView.UIDelegate = self;
appWebView.navigationDelegate = self;
[appWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString: @"http://#############"]]];

Here is the addUserScriptToUserContentController:

- (void) addUserScriptToUserContentController:(WKUserContentController *) userContentController{
NSString *jsHandler = [NSString stringWithContentsOfURL:[[NSBundle mainBundle]URLForResource:@"ajaxHandler" withExtension:@"js"] encoding:NSUTF8StringEncoding error:NULL];
WKUserScript *ajaxHandler = [[WKUserScript alloc]initWithSource:jsHandler injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:NO];
[userContentController addScriptMessageHandler:self name:@"callbackHandler"];
[userContentController addUserScript:ajaxHandler];
}

How to monitor http requests from WKWebView?

Ok, I found a way.

You can create a new class (let's call it MyURLProtocol) which has NSURLProtocol as subclass. Then add this function to MyURLProtocol:

+ (BOOL)canInitWithRequest:(NSURLRequest *)request {
NSLog(@"URL = %@", request.URL.absoluteString);
return NO;
}

This function will be called each time your webview makes a request. And then you need to register this protocol with the loading system. In your Appdelegate.m file include your class and add/replace didFinishLaunchingWithOptions function with this:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[NSURLProtocol registerClass:[MyURLProtocol class]];
return YES;
}

All set. Now you can edit canInitWithRequest function and do what you want with the request.

How to intercept all http(s) requests on ios WKWebView?

Take a look at this github repository called as WKWebViewWithURLProtocol Casolorz. This library enables you to use NSURLProtocol to intercept your network requests using method swizzling.

Intercept request with WKWebView

I see that after 5 years this question still generates curiosity, so I describe how I solved it and about some main problems I faced up.
As many who answered here, I have implemented WKURLSchemeHandler and used new schemes.

First of all the URL that wkwebview launches must not be HTTP (or HTTPS) but one of yours new schemes.

Example

mynewscheme://your-server-application.com

In you WKWebViewConfiguration conf, I set the handler:

[conf setURLSchemeHandler:[CustomSchemeHandler new] forURLScheme:@"mynewscheme"];
[conf setURLSchemeHandler:[CustomSchemeHandler new] forURLScheme:@"mynewschemesecure"];

In CustomSchemeHandler I have implemented webView:startURLSchemeTask: and webView:stopURLSchemeTask:.

In my case I check if the request is for a file that I just saved locally, otherwise I change actual protocol ("mynewscheme or "mynewschemesecure") with http (or https) and I make request by myself.

At this point I solved the "interception problem".

In this new way we have the webview "location" (location.href via javascript) with my new scheme and with it new problems started.

  • First problem is that my applications work mainly with javascript,
    and document.cookie has stopped working. I'm using Cordova
    framework, so I've develeped a plugin to set and get cookie to
    replace document.cookie (I had to do this, because, obviously, I
    have also http header set-cookie).

  • Second problem is that I've got a lot of "cross-origin" problems, then
    I changed all my urls in relative url (or with new schemes)

  • Third problem is that browser automatically handle server port 80
    and 443, omitting them, but has now stopped (maybe because of "not
    http location"). In my server code I had to handle this.

Writing down these few rows I admit that it seems to was an easy problem to solve, but I ensure that find out a workaround, how to solve it and integrate with the infinite amount of code has been hard. Every step towards the solution corresponded to a new problem.

How to monitor WKWebView page load progress in Swift?

Swift 4.0

@IBOutlet weak var webView: WKWebView!
@IBOutlet weak var progressView: UIProgressView!
override func viewDidLoad() {
super.viewDidLoad()

// load website or HTML page
self.webView.load(NSURLRequest(url: URL(string: "https://www.apple.com")!) as URLRequest);

//add observer to get estimated progress value
self.webView.addObserver(self, forKeyPath: "estimatedProgress", options: .new, context: nil);
}

// Observe value
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "estimatedProgress" {
print(self.webView.estimatedProgress);
self.progressView.progress = Float(self.webView.estimatedProgress);
}
}

WKWebView function for detecting if the URL has changed

What do you mean they don't always seem to fire? What kind of elements? They have to in order for the WkWebView to work.

Your first indication that the URL is trying to change is in: decidePolicyForNavigationAction

- (void) webView: (WKWebView *) webView decidePolicyForNavigationAction: (WKNavigationAction *) navigationAction decisionHandler: (void (^)(WKNavigationActionPolicy)) decisionHandler {
NSLog(@"%s", __PRETTY_FUNCTION__);
decisionHandler(WKNavigationActionPolicyAllow); //Always allow
NSURL *u1 = webView.URL;
NSURL *u2 = navigationAction.request.URL; //If changing URLs this one will be different
}

By the time you get to: didStartProvisionalNavigation It has changed.

- (void) webView: (WKWebView *) webView didStartProvisionalNavigation: (WKNavigation *) navigation {
NSLog(@"%s", __PRETTY_FUNCTION__);
NSURL *u1 = webView.URL; //By this time it's changed
}

All you'd have to do is implement these delegate methods (in Swift) and do what you want when you see it change.



Related Topics



Leave a reply



Submit