Obscure WebKit SPI

This commit is contained in:
2025-05-05 19:01:16 -07:00
parent 8fe8426cc2
commit 6301c40c59
5 changed files with 103 additions and 17 deletions

11
App/Hacks/Hacks.h Normal file
View File

@@ -0,0 +1,11 @@
//
// Hacks.h
// App
//
// Created by James Magahern on 5/5/25.
//
#import <Foundation/Foundation.h>
extern Class DecodedClass(const char *encodedClassName);
extern SEL DecodedSelector(const char *encodedSelectorName);

25
App/Hacks/Hacks.m Normal file
View File

@@ -0,0 +1,25 @@
//
// Hacks.m
// App
//
// Created by James Magahern on 5/5/25.
//
#import "Hacks.h"
Class DecodedClass(const char *encodedClassName) {
NSData *data = [NSData dataWithBytesNoCopy:(void *)encodedClassName length:strlen(encodedClassName) freeWhenDone:NO];
data = [[NSData alloc] initWithBase64EncodedData:data options:0];
NSString *str = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
return NSClassFromString(str);
}
SEL DecodedSelector(const char *encodedSelectorName) {
NSData *data = [NSData dataWithBytesNoCopy:(void *)encodedSelectorName length:strlen(encodedSelectorName) freeWhenDone:NO];
data = [[NSData alloc] initWithBase64EncodedData:data options:0];
NSString *str = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
return NSSelectorFromString(str);
}

View File

@@ -34,6 +34,8 @@
</array>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>

View File

@@ -8,18 +8,62 @@
#import "SBRProcessBundleBridge.h"
#import "SBRScriptPolicy.h"
#import "Hacks.h"
#import <OSLog/OSLog.h>
#import <WebKit/_WKRemoteObjectInterface.h>
#import <WebKit/_WKRemoteObjectRegistry.h>
#import <WebKit/_WKProcessPoolConfiguration.h>
#import <WebKit/_WKUserStyleSheet.h>
#import <WebKit/WKProcessPoolPrivate.h>
#import <WebKit/WKWebViewPrivate.h>
#import <WebKit/WKWebViewConfigurationPrivate.h>
#import <WebKit/WKUserContentControllerPrivate.h>
#define WKUserStyleSheet id
#define WKUserStyleSheetEncodedClassName "X1dLVXNlclN0eWxlU2hlZXQ="
@interface StyleSheet : NSObject <NSCopying>
@property (nonatomic, readonly, copy) NSString *source;
@property (nonatomic, readonly, copy) NSURL *baseURL;
@property (nonatomic, readonly, getter=isForMainFrameOnly) BOOL forMainFrameOnly;
- (instancetype)initWithSource:(NSString *)source forMainFrameOnly:(BOOL)forMainFrameOnly;
@end
@interface WKUserContentController (Private)
- (void)__addUserStyleSheet:(WKUserStyleSheet)userStyleSheet;
- (void)__removeUserStyleSheet:(WKUserStyleSheet)userStyleSheet;
- (void)__addUserScriptImmediately:(WKUserScript *)userScript;
@end
@implementation WKUserContentController (Private)
- (void)__addUserStyleSheet:(id)userStyleSheet
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[self performSelector:DecodedSelector("X2FkZFVzZXJTdHlsZVNoZWV0Og==") withObject:userStyleSheet];
#pragma clang diagnostic pop
}
- (void)__removeUserStyleSheet:(id)userStyleSheet
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[self performSelector:DecodedSelector("X3JlbW92ZVVzZXJTdHlsZVNoZWV0Og==") withObject:userStyleSheet];
#pragma clang diagnostic pop
}
- (void)__addUserScriptImmediately:(WKUserScript *)userScript
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[self performSelector:DecodedSelector("X2FkZFVzZXJTY3JpcHRJbW1lZGlhdGVseTo=") withObject:userScript];
#pragma clang diagnostic pop
}
@end
#define LOG_DEBUG(format, ...) os_log_debug(_log, format, ##__VA_ARGS__)
#define LOG_ERROR(format, ...) os_log_error(_log, format, ##__VA_ARGS__)
@@ -58,7 +102,7 @@
WKWebViewConfiguration *_webViewConfiguration;
WKProcessPool *_processPool;
_WKUserStyleSheet *_darkModeStyleSheet;
WKUserStyleSheet _darkModeStyleSheet;
WKUserScript *_readabilityScript;
NSArray<WKUserScript *> *_userScripts;
@@ -67,7 +111,7 @@
NSMutableDictionary<NSURLRequest *, NSURLSessionDataTask *> *_dataTasks;
// These come from settings.
_WKUserStyleSheet *_customizedUserStylesheet;
WKUserStyleSheet _customizedUserStylesheet;
WKUserScript *_customizedUserScript;
}
@@ -144,10 +188,8 @@
- (void)reloadCustomizedUserScriptsAndStylesheets
{
WKUserContentController *userContentController = [_webViewConfiguration userContentController];
if (_customizedUserScript) {
[userContentController _removeUserScript:_customizedUserScript];
}
[userContentController removeAllUserScripts];
NSString *scriptSource = [[NSUserDefaults standardUserDefaults] stringForKey:@"userScript"];
if ([scriptSource length]) {
_customizedUserScript = [[WKUserScript alloc] initWithSource:scriptSource injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
@@ -155,13 +197,13 @@
}
if (_customizedUserStylesheet) {
[userContentController _removeUserStyleSheet:_customizedUserStylesheet];
[userContentController __removeUserStyleSheet:_customizedUserStylesheet];
}
NSString *stylesheetSource = [[NSUserDefaults standardUserDefaults] stringForKey:@"userStylesheet"];
if ([stylesheetSource length]) {
_customizedUserStylesheet = [[_WKUserStyleSheet alloc] initWithSource:stylesheetSource forMainFrameOnly:YES];
[userContentController _addUserStyleSheet:_customizedUserStylesheet];
_customizedUserStylesheet = [[DecodedClass(WKUserStyleSheetEncodedClassName) alloc] initWithSource:stylesheetSource forMainFrameOnly:YES];
[userContentController __addUserStyleSheet:_customizedUserStylesheet];
}
}
@@ -284,12 +326,12 @@
if (!_darkModeStyleSheet) {
NSURL *styleSheetURL = [[NSBundle mainBundle] URLForResource:@"darkmode" withExtension:@"css"];
NSString *styleSheetSource = [NSString stringWithContentsOfURL:styleSheetURL encoding:NSUTF8StringEncoding error:nil];
_darkModeStyleSheet = [[_WKUserStyleSheet alloc] initWithSource:styleSheetSource forMainFrameOnly:NO];
_darkModeStyleSheet = [[DecodedClass(WKUserStyleSheetEncodedClassName) alloc] initWithSource:styleSheetSource forMainFrameOnly:NO];
}
[userContentController _addUserStyleSheet:_darkModeStyleSheet];
[userContentController __addUserStyleSheet:_darkModeStyleSheet];
} else if (_darkModeStyleSheet) {
[userContentController _removeUserStyleSheet:_darkModeStyleSheet];
[userContentController __removeUserStyleSheet:_darkModeStyleSheet];
}
}
@@ -301,7 +343,7 @@
_readabilityScript = [self _loadScriptForResource:@"Readability" withExtension:@"js"];
}
[userContentController _addUserScriptImmediately:_readabilityScript];
[userContentController __addUserScriptImmediately:_readabilityScript];
NSString *script = @""
"var documentClone = document.cloneNode(true);"