You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
198 lines
6.8 KiB
198 lines
6.8 KiB
//
|
|
// WKWebViewJavascriptBridge.m
|
|
//
|
|
// Created by @LokiMeyburg on 10/15/14.
|
|
// Copyright (c) 2014 @LokiMeyburg. All rights reserved.
|
|
//
|
|
|
|
|
|
#import "WKWebViewJavascriptBridge.h"
|
|
|
|
#if defined supportsWKWebView
|
|
|
|
@implementation WKWebViewJavascriptBridge {
|
|
__weak WKWebView* _webView;
|
|
__weak id<WKNavigationDelegate> _webViewDelegate;
|
|
long _uniqueId;
|
|
WebViewJavascriptBridgeBase *_base;
|
|
}
|
|
|
|
/* API
|
|
*****/
|
|
|
|
+ (void)enableLogging { [WebViewJavascriptBridgeBase enableLogging]; }
|
|
|
|
+ (instancetype)bridgeForWebView:(WKWebView*)webView {
|
|
WKWebViewJavascriptBridge* bridge = [[self alloc] init];
|
|
[bridge _setupInstance:webView];
|
|
[bridge reset];
|
|
return bridge;
|
|
}
|
|
|
|
- (void)send:(id)data {
|
|
[self send:data responseCallback:nil];
|
|
}
|
|
|
|
- (void)send:(id)data responseCallback:(WVJBResponseCallback)responseCallback {
|
|
[_base sendData:data responseCallback:responseCallback handlerName:nil];
|
|
}
|
|
|
|
- (void)callHandler:(NSString *)handlerName {
|
|
[self callHandler:handlerName data:nil responseCallback:nil];
|
|
}
|
|
|
|
- (void)callHandler:(NSString *)handlerName data:(id)data {
|
|
[self callHandler:handlerName data:data responseCallback:nil];
|
|
}
|
|
|
|
- (void)callHandler:(NSString *)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback {
|
|
[_base sendData:data responseCallback:responseCallback handlerName:handlerName];
|
|
}
|
|
|
|
- (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler {
|
|
_base.messageHandlers[handlerName] = [handler copy];
|
|
}
|
|
|
|
- (void)removeHandler:(NSString *)handlerName {
|
|
[_base.messageHandlers removeObjectForKey:handlerName];
|
|
}
|
|
|
|
- (void)reset {
|
|
[_base reset];
|
|
}
|
|
|
|
- (void)setWebViewDelegate:(id<WKNavigationDelegate>)webViewDelegate {
|
|
_webViewDelegate = webViewDelegate;
|
|
}
|
|
|
|
- (void)disableJavscriptAlertBoxSafetyTimeout {
|
|
[_base disableJavscriptAlertBoxSafetyTimeout];
|
|
}
|
|
|
|
/* Internals
|
|
***********/
|
|
|
|
- (void)dealloc {
|
|
_base = nil;
|
|
_webView = nil;
|
|
_webViewDelegate = nil;
|
|
_webView.navigationDelegate = nil;
|
|
}
|
|
|
|
|
|
/* WKWebView Specific Internals
|
|
******************************/
|
|
|
|
- (void) _setupInstance:(WKWebView*)webView {
|
|
_webView = webView;
|
|
_webView.navigationDelegate = self;
|
|
_base = [[WebViewJavascriptBridgeBase alloc] init];
|
|
_base.delegate = self;
|
|
}
|
|
|
|
|
|
- (void)WKFlushMessageQueue {
|
|
[_webView evaluateJavaScript:[_base webViewJavascriptFetchQueyCommand] completionHandler:^(NSString* result, NSError* error) {
|
|
if (error != nil) {
|
|
NSLog(@"WebViewJavascriptBridge: WARNING: Error when trying to fetch data from WKWebView: %@", error);
|
|
}
|
|
[_base flushMessageQueue:result];
|
|
}];
|
|
}
|
|
|
|
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
|
|
if (webView != _webView) { return; }
|
|
|
|
__strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate;
|
|
if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didFinishNavigation:)]) {
|
|
[strongDelegate webView:webView didFinishNavigation:navigation];
|
|
}
|
|
}
|
|
|
|
|
|
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {
|
|
if (webView != _webView) { return; }
|
|
|
|
__strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate;
|
|
if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:decidePolicyForNavigationResponse:decisionHandler:)]) {
|
|
[strongDelegate webView:webView decidePolicyForNavigationResponse:navigationResponse decisionHandler:decisionHandler];
|
|
}
|
|
else {
|
|
decisionHandler(WKNavigationResponsePolicyAllow);
|
|
}
|
|
}
|
|
|
|
- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler {
|
|
if (webView != _webView) { return; }
|
|
|
|
__strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate;
|
|
if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didReceiveAuthenticationChallenge:completionHandler:)]) {
|
|
[strongDelegate webView:webView didReceiveAuthenticationChallenge:challenge completionHandler:completionHandler];
|
|
} else {
|
|
completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
|
|
}
|
|
}
|
|
|
|
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
|
|
if (webView != _webView) { return; }
|
|
NSURL *url = navigationAction.request.URL;
|
|
__strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate;
|
|
|
|
if ([_base isWebViewJavascriptBridgeURL:url]) {
|
|
if ([_base isBridgeLoadedURL:url]) {
|
|
[_base injectJavascriptFile];
|
|
} else if ([_base isQueueMessageURL:url]) {
|
|
[self WKFlushMessageQueue];
|
|
} else {
|
|
[_base logUnkownMessage:url];
|
|
}
|
|
decisionHandler(WKNavigationActionPolicyCancel);
|
|
return;
|
|
}
|
|
|
|
if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:decidePolicyForNavigationAction:decisionHandler:)]) {
|
|
[_webViewDelegate webView:webView decidePolicyForNavigationAction:navigationAction decisionHandler:decisionHandler];
|
|
} else {
|
|
decisionHandler(WKNavigationActionPolicyAllow);
|
|
}
|
|
}
|
|
|
|
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
|
|
if (webView != _webView) { return; }
|
|
|
|
__strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate;
|
|
if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didStartProvisionalNavigation:)]) {
|
|
[strongDelegate webView:webView didStartProvisionalNavigation:navigation];
|
|
}
|
|
}
|
|
|
|
|
|
- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error {
|
|
if (webView != _webView) { return; }
|
|
|
|
__strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate;
|
|
if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didFailNavigation:withError:)]) {
|
|
[strongDelegate webView:webView didFailNavigation:navigation withError:error];
|
|
}
|
|
}
|
|
|
|
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error {
|
|
if (webView != _webView) { return; }
|
|
|
|
__strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate;
|
|
if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didFailProvisionalNavigation:withError:)]) {
|
|
[strongDelegate webView:webView didFailProvisionalNavigation:navigation withError:error];
|
|
}
|
|
}
|
|
|
|
- (NSString*) _evaluateJavascript:(NSString*)javascriptCommand {
|
|
[_webView evaluateJavaScript:javascriptCommand completionHandler:nil];
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
#endif
|
|
|