javascript 如何监控 WKWebview 上的请求?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28766676/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can i monitor requests on WKWebview?
提问by Benzi Heler
How can i monitor requests on WKWebview?
如何监控 WKWebview 上的请求?
I'v tried using NSURLprotocol (canInitWithRequest) but it won't monitor ajax requests (XHR), only navigation requests(document requests)
我试过使用 NSURLprotocol (canInitWithRequest) 但它不会监控 ajax 请求 (XHR),只有导航请求(文档请求)
回答by Benzi Heler
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.
由于我无法控制 Web 视图内容,因此我向 WKWebview 注入了一个包含 jQuery AJAX 请求侦听器的 Java 脚本。
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 -
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:
我的 ViewController 委托是:
@interface BrowserViewController : UIViewController <UIWebViewDelegate, WKUIDelegate, WKNavigationDelegate, WKScriptMessageHandler, UIWebViewDelegate>
And in my viewDidLoad()
, I'm creating a WKWebView:
在我的 中viewDidLoad()
,我正在创建一个 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:
这是 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];
}
回答by user3448282
@Benzi Heler answer is great, but it uses jQuery which seems like is not working in WKWebView
anymore, so I have found solution without using jQuery.
@Benzi Heler 的回答很棒,但它使用的 jQuery 似乎WKWebView
不再适用,所以我找到了不使用 jQuery 的解决方案。
Here is ViewController implementation that lets you be notified every AJAX request is completed in WKWebView
:
这是 ViewController 实现,它可以让您在每个 AJAX 请求完成时收到通知WKWebView
:
import UIKit
import WebKit
class WebViewController: UIViewController {
private var wkWebView: WKWebView!
private let handler = "handler"
override func viewDidLoad() {
super.viewDidLoad()
let config = WKWebViewConfiguration()
let userScript = WKUserScript(source: getScript(), injectionTime: .atDocumentStart, forMainFrameOnly: false)
config.userContentController.addUserScript(userScript)
config.userContentController.add(self, name: handler)
wkWebView = WKWebView(frame: view.bounds, configuration: config)
view.addSubview(wkWebView)
if let url = URL(string: "YOUR AJAX WEBSITE") {
wkWebView.load(URLRequest(url: url))
} else {
print("Wrong URL!")
}
}
private func getScript() -> String {
if let filepath = Bundle.main.path(forResource: "script", ofType: "js") {
do {
return try String(contentsOfFile: filepath)
} catch {
print(error)
}
} else {
print("script.js not found!")
}
return ""
}
}
extension WebViewController: WKScriptMessageHandler {
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
if let dict = message.body as? Dictionary<String, AnyObject>, let status = dict["status"] as? Int, let responseUrl = dict["responseURL"] as? String {
print(status)
print(responseUrl)
}
}
}
Pretty standard implementation. There is a WKWebView
created programmatically. There is injected script that is loaded from script.js
file.
相当标准的实现。有一个以WKWebView
编程方式创建的。有从script.js
文件加载的注入脚本。
And the most important part is script.js
file:
最重要的部分是script.js
文件:
var open = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function() {
this.addEventListener("load", function() {
var message = {"status" : this.status, "responseURL" : this.responseURL}
webkit.messageHandlers.handler.postMessage(message);
});
open.apply(this, arguments);
};
userContentController
delegate method will be called every time there is AJAX request loaded. I'm passing there status
and responseURL
, because this was what I needed in my case, but you can also get more informations about request. Here is the list of all properties and methods available:
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
userContentController
每次加载 AJAX 请求时都会调用委托方法。我路过那里status
和responseURL
,因为这是我需要在我的情况是什么,但你也可以获取有关请求的更多信息。以下是所有可用属性和方法的列表:https:
//developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
My solution is inspired by this answer written by @John Culviner: https://stackoverflow.com/a/27363569/3448282
我的解决方案的灵感来自@John Culviner 写的这个答案:https://stackoverflow.com/a/27363569/3448282
回答by Justin Michael
If you have control of the content inside the WkWebView
you can send messages to your native app using window.webkit.messageHandlers
whenever you make an ajax request, which will be received as a WKScriptMessage
that can be processed by whatever you've designated as your WKScriptMessageHandler
. The messages can contain whatever information you wish, and will be automatically converted into native objects/values in your Objective-C or Swift code.
如果您可以控制其中的内容,则WkWebView
可以window.webkit.messageHandlers
在每次发出 ajax 请求时使用向您的本机应用程序发送消息,该请求将作为 a 接收WKScriptMessage
,可以由您指定为WKScriptMessageHandler
. 这些消息可以包含您想要的任何信息,并且会在您的 Objective-C 或 Swift 代码中自动转换为原生对象/值。
If you don't have control over the content you can still do this by injecting your own JavaScript via a WKUserScript
to track ajax requests and send back messages using the method stated above.
如果您无法控制内容,您仍然可以通过 a 注入您自己的 JavaScriptWKUserScript
来跟踪 ajax 请求并使用上述方法发回消息。