Obscure WebKit SPI
This commit is contained in:
11
App/Hacks/Hacks.h
Normal file
11
App/Hacks/Hacks.h
Normal 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
25
App/Hacks/Hacks.m
Normal 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);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -34,6 +34,8 @@
|
|||||||
</array>
|
</array>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||||
|
<key>LSApplicationCategoryType</key>
|
||||||
|
<string>public.app-category.utilities</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>NSAppTransportSecurity</key>
|
<key>NSAppTransportSecurity</key>
|
||||||
|
|||||||
@@ -8,18 +8,62 @@
|
|||||||
#import "SBRProcessBundleBridge.h"
|
#import "SBRProcessBundleBridge.h"
|
||||||
|
|
||||||
#import "SBRScriptPolicy.h"
|
#import "SBRScriptPolicy.h"
|
||||||
|
#import "Hacks.h"
|
||||||
|
|
||||||
#import <OSLog/OSLog.h>
|
#import <OSLog/OSLog.h>
|
||||||
|
|
||||||
#import <WebKit/_WKRemoteObjectInterface.h>
|
#import <WebKit/_WKRemoteObjectInterface.h>
|
||||||
#import <WebKit/_WKRemoteObjectRegistry.h>
|
#import <WebKit/_WKRemoteObjectRegistry.h>
|
||||||
#import <WebKit/_WKProcessPoolConfiguration.h>
|
#import <WebKit/_WKProcessPoolConfiguration.h>
|
||||||
#import <WebKit/_WKUserStyleSheet.h>
|
|
||||||
|
|
||||||
#import <WebKit/WKProcessPoolPrivate.h>
|
#import <WebKit/WKProcessPoolPrivate.h>
|
||||||
#import <WebKit/WKWebViewPrivate.h>
|
#import <WebKit/WKWebViewPrivate.h>
|
||||||
#import <WebKit/WKWebViewConfigurationPrivate.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_DEBUG(format, ...) os_log_debug(_log, format, ##__VA_ARGS__)
|
||||||
#define LOG_ERROR(format, ...) os_log_error(_log, format, ##__VA_ARGS__)
|
#define LOG_ERROR(format, ...) os_log_error(_log, format, ##__VA_ARGS__)
|
||||||
@@ -58,7 +102,7 @@
|
|||||||
WKWebViewConfiguration *_webViewConfiguration;
|
WKWebViewConfiguration *_webViewConfiguration;
|
||||||
WKProcessPool *_processPool;
|
WKProcessPool *_processPool;
|
||||||
|
|
||||||
_WKUserStyleSheet *_darkModeStyleSheet;
|
WKUserStyleSheet _darkModeStyleSheet;
|
||||||
WKUserScript *_readabilityScript;
|
WKUserScript *_readabilityScript;
|
||||||
|
|
||||||
NSArray<WKUserScript *> *_userScripts;
|
NSArray<WKUserScript *> *_userScripts;
|
||||||
@@ -67,7 +111,7 @@
|
|||||||
NSMutableDictionary<NSURLRequest *, NSURLSessionDataTask *> *_dataTasks;
|
NSMutableDictionary<NSURLRequest *, NSURLSessionDataTask *> *_dataTasks;
|
||||||
|
|
||||||
// These come from settings.
|
// These come from settings.
|
||||||
_WKUserStyleSheet *_customizedUserStylesheet;
|
WKUserStyleSheet _customizedUserStylesheet;
|
||||||
WKUserScript *_customizedUserScript;
|
WKUserScript *_customizedUserScript;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,9 +188,7 @@
|
|||||||
- (void)reloadCustomizedUserScriptsAndStylesheets
|
- (void)reloadCustomizedUserScriptsAndStylesheets
|
||||||
{
|
{
|
||||||
WKUserContentController *userContentController = [_webViewConfiguration userContentController];
|
WKUserContentController *userContentController = [_webViewConfiguration userContentController];
|
||||||
if (_customizedUserScript) {
|
[userContentController removeAllUserScripts];
|
||||||
[userContentController _removeUserScript:_customizedUserScript];
|
|
||||||
}
|
|
||||||
|
|
||||||
NSString *scriptSource = [[NSUserDefaults standardUserDefaults] stringForKey:@"userScript"];
|
NSString *scriptSource = [[NSUserDefaults standardUserDefaults] stringForKey:@"userScript"];
|
||||||
if ([scriptSource length]) {
|
if ([scriptSource length]) {
|
||||||
@@ -155,13 +197,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_customizedUserStylesheet) {
|
if (_customizedUserStylesheet) {
|
||||||
[userContentController _removeUserStyleSheet:_customizedUserStylesheet];
|
[userContentController __removeUserStyleSheet:_customizedUserStylesheet];
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString *stylesheetSource = [[NSUserDefaults standardUserDefaults] stringForKey:@"userStylesheet"];
|
NSString *stylesheetSource = [[NSUserDefaults standardUserDefaults] stringForKey:@"userStylesheet"];
|
||||||
if ([stylesheetSource length]) {
|
if ([stylesheetSource length]) {
|
||||||
_customizedUserStylesheet = [[_WKUserStyleSheet alloc] initWithSource:stylesheetSource forMainFrameOnly:YES];
|
_customizedUserStylesheet = [[DecodedClass(WKUserStyleSheetEncodedClassName) alloc] initWithSource:stylesheetSource forMainFrameOnly:YES];
|
||||||
[userContentController _addUserStyleSheet:_customizedUserStylesheet];
|
[userContentController __addUserStyleSheet:_customizedUserStylesheet];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,12 +326,12 @@
|
|||||||
if (!_darkModeStyleSheet) {
|
if (!_darkModeStyleSheet) {
|
||||||
NSURL *styleSheetURL = [[NSBundle mainBundle] URLForResource:@"darkmode" withExtension:@"css"];
|
NSURL *styleSheetURL = [[NSBundle mainBundle] URLForResource:@"darkmode" withExtension:@"css"];
|
||||||
NSString *styleSheetSource = [NSString stringWithContentsOfURL:styleSheetURL encoding:NSUTF8StringEncoding error:nil];
|
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) {
|
} else if (_darkModeStyleSheet) {
|
||||||
[userContentController _removeUserStyleSheet:_darkModeStyleSheet];
|
[userContentController __removeUserStyleSheet:_darkModeStyleSheet];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,7 +343,7 @@
|
|||||||
_readabilityScript = [self _loadScriptForResource:@"Readability" withExtension:@"js"];
|
_readabilityScript = [self _loadScriptForResource:@"Readability" withExtension:@"js"];
|
||||||
}
|
}
|
||||||
|
|
||||||
[userContentController _addUserScriptImmediately:_readabilityScript];
|
[userContentController __addUserScriptImmediately:_readabilityScript];
|
||||||
|
|
||||||
NSString *script = @""
|
NSString *script = @""
|
||||||
"var documentClone = document.cloneNode(true);"
|
"var documentClone = document.cloneNode(true);"
|
||||||
|
|||||||
@@ -56,6 +56,7 @@
|
|||||||
CD853BCE24E7763900D2BDCC /* BrowserHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD853BCD24E7763900D2BDCC /* BrowserHistory.swift */; };
|
CD853BCE24E7763900D2BDCC /* BrowserHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD853BCD24E7763900D2BDCC /* BrowserHistory.swift */; };
|
||||||
CD853BD124E778B800D2BDCC /* History.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = CD853BCF24E778B800D2BDCC /* History.xcdatamodeld */; };
|
CD853BD124E778B800D2BDCC /* History.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = CD853BCF24E778B800D2BDCC /* History.xcdatamodeld */; };
|
||||||
CD853BD424E77BF900D2BDCC /* HistoryItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD853BD324E77BF900D2BDCC /* HistoryItem.swift */; };
|
CD853BD424E77BF900D2BDCC /* HistoryItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD853BD324E77BF900D2BDCC /* HistoryItem.swift */; };
|
||||||
|
CD8ACBC22DC9A2F7008BF856 /* Hacks.m in Sources */ = {isa = PBXBuildFile; fileRef = CD8ACBC12DC9A2F7008BF856 /* Hacks.m */; };
|
||||||
CD8DBE7B2A85D892006A0FE0 /* LayoutLatch.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD8DBE7A2A85D892006A0FE0 /* LayoutLatch.swift */; };
|
CD8DBE7B2A85D892006A0FE0 /* LayoutLatch.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD8DBE7A2A85D892006A0FE0 /* LayoutLatch.swift */; };
|
||||||
CD936A3B289DB3380093A1AC /* TabInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD936A3A289DB3380093A1AC /* TabInfo.swift */; };
|
CD936A3B289DB3380093A1AC /* TabInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD936A3A289DB3380093A1AC /* TabInfo.swift */; };
|
||||||
CD936A3D289DB88B0093A1AC /* UIView+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD936A3C289DB88B0093A1AC /* UIView+Utils.swift */; };
|
CD936A3D289DB88B0093A1AC /* UIView+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD936A3C289DB88B0093A1AC /* UIView+Utils.swift */; };
|
||||||
@@ -154,6 +155,8 @@
|
|||||||
CD853BCD24E7763900D2BDCC /* BrowserHistory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserHistory.swift; sourceTree = "<group>"; };
|
CD853BCD24E7763900D2BDCC /* BrowserHistory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserHistory.swift; sourceTree = "<group>"; };
|
||||||
CD853BD024E778B800D2BDCC /* History.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = History.xcdatamodel; sourceTree = "<group>"; };
|
CD853BD024E778B800D2BDCC /* History.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = History.xcdatamodel; sourceTree = "<group>"; };
|
||||||
CD853BD324E77BF900D2BDCC /* HistoryItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryItem.swift; sourceTree = "<group>"; };
|
CD853BD324E77BF900D2BDCC /* HistoryItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryItem.swift; sourceTree = "<group>"; };
|
||||||
|
CD8ACBC02DC9A2F7008BF856 /* Hacks.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Hacks.h; sourceTree = "<group>"; };
|
||||||
|
CD8ACBC12DC9A2F7008BF856 /* Hacks.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Hacks.m; sourceTree = "<group>"; };
|
||||||
CD8DBE7A2A85D892006A0FE0 /* LayoutLatch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayoutLatch.swift; sourceTree = "<group>"; };
|
CD8DBE7A2A85D892006A0FE0 /* LayoutLatch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayoutLatch.swift; sourceTree = "<group>"; };
|
||||||
CD936A3A289DB3380093A1AC /* TabInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabInfo.swift; sourceTree = "<group>"; };
|
CD936A3A289DB3380093A1AC /* TabInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabInfo.swift; sourceTree = "<group>"; };
|
||||||
CD936A3C289DB88B0093A1AC /* UIView+Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Utils.swift"; sourceTree = "<group>"; };
|
CD936A3C289DB88B0093A1AC /* UIView+Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Utils.swift"; sourceTree = "<group>"; };
|
||||||
@@ -410,6 +413,8 @@
|
|||||||
CD7F2133265DACEE0001D042 /* Hacks */ = {
|
CD7F2133265DACEE0001D042 /* Hacks */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
CD8ACBC02DC9A2F7008BF856 /* Hacks.h */,
|
||||||
|
CD8ACBC12DC9A2F7008BF856 /* Hacks.m */,
|
||||||
CD7F2134265DAD010001D042 /* MFMailComposeViewControllerFix.m */,
|
CD7F2134265DAD010001D042 /* MFMailComposeViewControllerFix.m */,
|
||||||
);
|
);
|
||||||
path = Hacks;
|
path = Hacks;
|
||||||
@@ -566,6 +571,7 @@
|
|||||||
1AD3104325254FB900A4A952 /* FindOnPageViewController.swift in Sources */,
|
1AD3104325254FB900A4A952 /* FindOnPageViewController.swift in Sources */,
|
||||||
1A03811424E73EB300826501 /* SegmentedReliefButton.swift in Sources */,
|
1A03811424E73EB300826501 /* SegmentedReliefButton.swift in Sources */,
|
||||||
1A03811024E71CF000826501 /* ReliefButton.swift in Sources */,
|
1A03811024E71CF000826501 /* ReliefButton.swift in Sources */,
|
||||||
|
CD8ACBC22DC9A2F7008BF856 /* Hacks.m in Sources */,
|
||||||
1A03811224E71EAA00826501 /* GradientView.swift in Sources */,
|
1A03811224E71EAA00826501 /* GradientView.swift in Sources */,
|
||||||
1ADFF4C024CA6964006DC7AE /* URLBar.swift in Sources */,
|
1ADFF4C024CA6964006DC7AE /* URLBar.swift in Sources */,
|
||||||
CDAD9CEA263A318F00FF7199 /* ShareableURL.swift in Sources */,
|
CDAD9CEA263A318F00FF7199 /* ShareableURL.swift in Sources */,
|
||||||
@@ -776,7 +782,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = "App/Supporting Files/SBrowser.entitlements";
|
CODE_SIGN_ENTITLEMENTS = "App/Supporting Files/SBrowser.entitlements";
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 4;
|
CURRENT_PROJECT_VERSION = 5;
|
||||||
DEAD_CODE_STRIPPING = YES;
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEVELOPMENT_TEAM = DQQH5H6GBD;
|
DEVELOPMENT_TEAM = DQQH5H6GBD;
|
||||||
INFOPLIST_FILE = "App/Supporting Files/Info.plist";
|
INFOPLIST_FILE = "App/Supporting Files/Info.plist";
|
||||||
@@ -811,7 +817,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = "App/Supporting Files/SBrowser.entitlements";
|
CODE_SIGN_ENTITLEMENTS = "App/Supporting Files/SBrowser.entitlements";
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 4;
|
CURRENT_PROJECT_VERSION = 5;
|
||||||
DEAD_CODE_STRIPPING = YES;
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEVELOPMENT_TEAM = DQQH5H6GBD;
|
DEVELOPMENT_TEAM = DQQH5H6GBD;
|
||||||
INFOPLIST_FILE = "App/Supporting Files/Info.plist";
|
INFOPLIST_FILE = "App/Supporting Files/Info.plist";
|
||||||
|
|||||||
Reference in New Issue
Block a user