EMASCurlWeb/EMASCurlWebContentLoader.m (69 lines of code) (raw):
//
// EMASCurlWkWebViewContentLoader.m
// EMASCurl
//
// Created by xuyecan on 2025/2/4.
//
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <WebKit/WebKit.h>
#import "EMASCurlWebUrlSchemeHandler.h"
#import "EMASCurlWebContentLoader.h"
#import "EMASCurlWebLogger.h"
#import "EMASCurlWebUtils.h"
static void *kEMASCurlStoreConfigurationKey = &kEMASCurlStoreConfigurationKey;
@implementation EMASCurlWebContentLoader
+ (void)initializeInterception {
[self swizzleWkWebViewMethod];
[self swizzleWkWebViewConfigurationMethod];
}
+ (void)setDebugLogEnabled:(BOOL)enabled {
[EMASCurlWebLogger setDebugLogEnabled:enabled];
}
+ (void)swizzleWkWebViewMethod {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class cls = [WKWebView class];
{
__block BOOL (*oldImp)(id,SEL,id) = NULL;
SEL sel = @selector(handlesURLScheme:);
IMP newImp = imp_implementationWithBlock(^(id obj, NSString* scheme){
return NO;
});
Method method = class_getInstanceMethod(object_getClass(cls), sel);
oldImp = (BOOL (*)(id,SEL,id))method_getImplementation(method);
if (!class_addMethod(object_getClass(cls), sel, newImp, method_getTypeEncoding(method))) {
method_setImplementation(method, newImp);
}
}
{
__block WKWebView* (*oldImp)(id,SEL,CGRect,id) = NULL;
SEL sel = @selector(initWithFrame:configuration:);
IMP newImp = imp_implementationWithBlock(^(id obj, CGRect frame, WKWebViewConfiguration*configuration){
WKWebView *webview = oldImp(obj, sel, frame, configuration);
objc_setAssociatedObject(webview, kEMASCurlStoreConfigurationKey, configuration, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
[configuration setWkWebView:webview];
return webview;
});
Method method = class_getInstanceMethod(cls, sel);
oldImp = (WKWebView* (*)(id, SEL, CGRect, id))method_getImplementation(method);
if (!class_addMethod(cls, sel, newImp, method_getTypeEncoding(method))) {
oldImp = (WKWebView* (*)(id, SEL, CGRect, id))method_setImplementation(method, newImp);
}
}
});
}
+ (void)swizzleWkWebViewConfigurationMethod {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class cls = [WKWebViewConfiguration class];
__block void * (*oldImp)(id, SEL, id, id) = NULL;
SEL sel = @selector(setURLSchemeHandler:forURLScheme:);
IMP newImp = imp_implementationWithBlock(^(id obj, id<WKURLSchemeHandler> schemeHandler, NSString *scheme) {
oldImp(obj, sel, schemeHandler, scheme);
void *storeKey = (__bridge void*)[EMASCurlWebUrlSchemeHandler class];
EMASCurlWebWeakProxy *redirectDelegateProxy = [[EMASCurlWebWeakProxy alloc] initWithObject:obj];
objc_setAssociatedObject(schemeHandler, storeKey, redirectDelegateProxy, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
});
Method method = class_getInstanceMethod(cls, sel);
oldImp = (void * (*)(id, SEL, id, id))method_getImplementation(method);
if (!class_addMethod(cls, sel, newImp, method_getTypeEncoding(method))) {
method_setImplementation(method, newImp);
}
});
}
@end