172 lines
7.6 KiB
Objective-C
172 lines
7.6 KiB
Objective-C
//
|
|
// WKWebView+Swizzling.m
|
|
// 1233213
|
|
//
|
|
// Created by man 2019/1/8.
|
|
// Copyright © 2020 man. All rights reserved.
|
|
//
|
|
|
|
#import <WebKit/WebKit.h>
|
|
#import <objc/runtime.h>
|
|
#import "_ObjcLog.h"
|
|
#import "_NetworkHelper.h"
|
|
|
|
@interface WKWebView () <WKScriptMessageHandler>
|
|
|
|
@end
|
|
|
|
@implementation WKWebView (_Swizzling)
|
|
|
|
#pragma mark - life
|
|
+ (void)load {
|
|
|
|
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"enableWKWebViewMonitoring_CocoaDebug"]) {
|
|
|
|
static dispatch_once_t onceToken;
|
|
dispatch_once(&onceToken, ^{
|
|
|
|
SEL original_sel = @selector(initWithFrame:configuration:);
|
|
SEL replaced_sel = @selector(replaced_initWithFrame:configuration:);
|
|
Method original_method = class_getInstanceMethod([self class], original_sel);
|
|
Method replaced_method = class_getInstanceMethod([self class], replaced_sel);
|
|
if (!class_addMethod([self class], original_sel, method_getImplementation(replaced_method), method_getTypeEncoding(replaced_method))) {
|
|
method_exchangeImplementations(original_method, replaced_method);
|
|
}
|
|
|
|
/*********************************************************************************************************************************/
|
|
|
|
SEL original_sel2 = NSSelectorFromString(@"dealloc");
|
|
SEL replaced_sel2 = @selector(replaced_dealloc);
|
|
Method original_method2 = class_getInstanceMethod([self class], original_sel2);
|
|
Method replaced_method2 = class_getInstanceMethod([self class], replaced_sel2);
|
|
if (!class_addMethod([self class], original_sel2, method_getImplementation(replaced_method2), method_getTypeEncoding(replaced_method2))) {
|
|
method_exchangeImplementations(original_method2, replaced_method2);
|
|
}
|
|
|
|
SEL original_sel3 = NSSelectorFromString(@"willDealloc");
|
|
SEL replaced_sel3 = @selector(replaced_willDealloc);
|
|
Method replaced_method3 = class_getInstanceMethod([self class], replaced_sel3);
|
|
class_addMethod([self class], original_sel3, method_getImplementation(replaced_method3), method_getTypeEncoding(replaced_method3));
|
|
});
|
|
}
|
|
}
|
|
|
|
#pragma mark - replaced method
|
|
|
|
- (BOOL)replaced_willDealloc {
|
|
// removeScriptMessageHandlerForName
|
|
[self.configuration.userContentController removeScriptMessageHandlerForName:@"log"];
|
|
[self.configuration.userContentController removeScriptMessageHandlerForName:@"error"];
|
|
[self.configuration.userContentController removeScriptMessageHandlerForName:@"warn"];
|
|
[self.configuration.userContentController removeScriptMessageHandlerForName:@"debug"];
|
|
[self.configuration.userContentController removeScriptMessageHandlerForName:@"info"];
|
|
|
|
return true;
|
|
}
|
|
|
|
- (void)replaced_dealloc {
|
|
//WKWebView
|
|
[_ObjcLog logWithFile:"[WKWebView]" function:"" line:0 color:[UIColor redColor] message:@"-------------------------------- dealloc --------------------------------"];
|
|
}
|
|
|
|
- (instancetype)replaced_initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration {
|
|
//WKWebView
|
|
[_ObjcLog logWithFile:"[WKWebView]" function:"" line:0 color:[_NetworkHelper shared].mainColor message:@"----------------------------------- init -----------------------------------"];
|
|
|
|
[self log:configuration];
|
|
[self error:configuration];
|
|
[self warn:configuration];
|
|
[self debug:configuration];
|
|
[self info:configuration];
|
|
|
|
return [self replaced_initWithFrame:frame configuration:configuration];
|
|
}
|
|
|
|
#pragma mark - private
|
|
- (void)log:(WKWebViewConfiguration *)configuration {
|
|
[configuration.userContentController removeScriptMessageHandlerForName:@"log"];
|
|
[configuration.userContentController addScriptMessageHandler:self name:@"log"];
|
|
//rewrite the method of console.log
|
|
NSString *jsCode = @"console.log = (function(oriLogFunc){\
|
|
return function(str)\
|
|
{\
|
|
window.webkit.messageHandlers.log.postMessage(str);\
|
|
oriLogFunc.call(console,str);\
|
|
}\
|
|
})(console.log);";
|
|
//injected the method when H5 starts to create the DOM tree
|
|
[configuration.userContentController addUserScript:[[WKUserScript alloc] initWithSource:jsCode injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]];
|
|
}
|
|
|
|
- (void)error:(WKWebViewConfiguration *)configuration {
|
|
[configuration.userContentController removeScriptMessageHandlerForName:@"error"];
|
|
[configuration.userContentController addScriptMessageHandler:self name:@"error"];
|
|
//rewrite the method of console.error
|
|
NSString *jsCode = @"console.error = (function(oriLogFunc){\
|
|
return function(str)\
|
|
{\
|
|
window.webkit.messageHandlers.error.postMessage(str);\
|
|
oriLogFunc.call(console,str);\
|
|
}\
|
|
})(console.error);";
|
|
//injected the method when H5 starts to create the DOM tree
|
|
[configuration.userContentController addUserScript:[[WKUserScript alloc] initWithSource:jsCode injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]];
|
|
}
|
|
|
|
- (void)warn:(WKWebViewConfiguration *)configuration {
|
|
[configuration.userContentController removeScriptMessageHandlerForName:@"warn"];
|
|
[configuration.userContentController addScriptMessageHandler:self name:@"warn"];
|
|
//rewrite the method of console.warn
|
|
NSString *jsCode = @"console.warn = (function(oriLogFunc){\
|
|
return function(str)\
|
|
{\
|
|
window.webkit.messageHandlers.warn.postMessage(str);\
|
|
oriLogFunc.call(console,str);\
|
|
}\
|
|
})(console.warn);";
|
|
//injected the method when H5 starts to create the DOM tree
|
|
[configuration.userContentController addUserScript:[[WKUserScript alloc] initWithSource:jsCode injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]];
|
|
}
|
|
|
|
- (void)debug:(WKWebViewConfiguration *)configuration {
|
|
[configuration.userContentController removeScriptMessageHandlerForName:@"debug"];
|
|
[configuration.userContentController addScriptMessageHandler:self name:@"debug"];
|
|
//rewrite the method of console.debug
|
|
NSString *jsCode = @"console.debug = (function(oriLogFunc){\
|
|
return function(str)\
|
|
{\
|
|
window.webkit.messageHandlers.debug.postMessage(str);\
|
|
oriLogFunc.call(console,str);\
|
|
}\
|
|
})(console.debug);";
|
|
//injected the method when H5 starts to create the DOM tree
|
|
[configuration.userContentController addUserScript:[[WKUserScript alloc] initWithSource:jsCode injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]];
|
|
}
|
|
|
|
- (void)info:(WKWebViewConfiguration *)configuration {
|
|
[configuration.userContentController removeScriptMessageHandlerForName:@"info"];
|
|
[configuration.userContentController addScriptMessageHandler:self name:@"info"];
|
|
//rewrite the method of console.info
|
|
NSString *jsCode = @"console.info = (function(oriLogFunc){\
|
|
return function(str)\
|
|
{\
|
|
window.webkit.messageHandlers.info.postMessage(str);\
|
|
oriLogFunc.call(console,str);\
|
|
}\
|
|
})(console.info);";
|
|
//injected the method when H5 starts to create the DOM tree
|
|
[configuration.userContentController addUserScript:[[WKUserScript alloc] initWithSource:jsCode injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]];
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - WKScriptMessageHandler
|
|
#pragma clang diagnostic push
|
|
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
|
|
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
|
|
[_ObjcLog logWithFile:"[WKWebView]" function:[message.name UTF8String] line:0 color:[UIColor whiteColor] message:message.body];
|
|
}
|
|
#pragma clang diagnostic pop
|
|
|
|
@end
|