diff --git a/App/Hacks/Hacks.h b/App/Hacks/Hacks.h new file mode 100644 index 0000000..8c2484a --- /dev/null +++ b/App/Hacks/Hacks.h @@ -0,0 +1,11 @@ +// +// Hacks.h +// App +// +// Created by James Magahern on 5/5/25. +// + +#import + +extern Class DecodedClass(const char *encodedClassName); +extern SEL DecodedSelector(const char *encodedSelectorName); diff --git a/App/Hacks/Hacks.m b/App/Hacks/Hacks.m new file mode 100644 index 0000000..ee55086 --- /dev/null +++ b/App/Hacks/Hacks.m @@ -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); +} + diff --git a/App/Supporting Files/Info.plist b/App/Supporting Files/Info.plist index 2311df4..e28053b 100644 --- a/App/Supporting Files/Info.plist +++ b/App/Supporting Files/Info.plist @@ -34,6 +34,8 @@ CFBundleVersion $(CURRENT_PROJECT_VERSION) + LSApplicationCategoryType + public.app-category.utilities LSRequiresIPhoneOS NSAppTransportSecurity diff --git a/App/Web Process Bundle Bridge/SBRProcessBundleBridge.m b/App/Web Process Bundle Bridge/SBRProcessBundleBridge.m index 1473a5a..f5f08bb 100644 --- a/App/Web Process Bundle Bridge/SBRProcessBundleBridge.m +++ b/App/Web Process Bundle Bridge/SBRProcessBundleBridge.m @@ -8,18 +8,62 @@ #import "SBRProcessBundleBridge.h" #import "SBRScriptPolicy.h" +#import "Hacks.h" #import #import #import #import -#import #import #import #import -#import + +#define WKUserStyleSheet id +#define WKUserStyleSheetEncodedClassName "X1dLVXNlclN0eWxlU2hlZXQ=" + +@interface StyleSheet : NSObject +@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 *_userScripts; @@ -67,7 +111,7 @@ NSMutableDictionary *_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);" diff --git a/SBrowser.xcodeproj/project.pbxproj b/SBrowser.xcodeproj/project.pbxproj index 05384c2..411e95b 100644 --- a/SBrowser.xcodeproj/project.pbxproj +++ b/SBrowser.xcodeproj/project.pbxproj @@ -56,6 +56,7 @@ CD853BCE24E7763900D2BDCC /* BrowserHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD853BCD24E7763900D2BDCC /* BrowserHistory.swift */; }; CD853BD124E778B800D2BDCC /* History.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = CD853BCF24E778B800D2BDCC /* History.xcdatamodeld */; }; 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 */; }; CD936A3B289DB3380093A1AC /* TabInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD936A3A289DB3380093A1AC /* TabInfo.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 = ""; }; CD853BD024E778B800D2BDCC /* History.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = History.xcdatamodel; sourceTree = ""; }; CD853BD324E77BF900D2BDCC /* HistoryItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryItem.swift; sourceTree = ""; }; + CD8ACBC02DC9A2F7008BF856 /* Hacks.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Hacks.h; sourceTree = ""; }; + CD8ACBC12DC9A2F7008BF856 /* Hacks.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Hacks.m; sourceTree = ""; }; CD8DBE7A2A85D892006A0FE0 /* LayoutLatch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayoutLatch.swift; sourceTree = ""; }; CD936A3A289DB3380093A1AC /* TabInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabInfo.swift; sourceTree = ""; }; CD936A3C289DB88B0093A1AC /* UIView+Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Utils.swift"; sourceTree = ""; }; @@ -410,6 +413,8 @@ CD7F2133265DACEE0001D042 /* Hacks */ = { isa = PBXGroup; children = ( + CD8ACBC02DC9A2F7008BF856 /* Hacks.h */, + CD8ACBC12DC9A2F7008BF856 /* Hacks.m */, CD7F2134265DAD010001D042 /* MFMailComposeViewControllerFix.m */, ); path = Hacks; @@ -566,6 +571,7 @@ 1AD3104325254FB900A4A952 /* FindOnPageViewController.swift in Sources */, 1A03811424E73EB300826501 /* SegmentedReliefButton.swift in Sources */, 1A03811024E71CF000826501 /* ReliefButton.swift in Sources */, + CD8ACBC22DC9A2F7008BF856 /* Hacks.m in Sources */, 1A03811224E71EAA00826501 /* GradientView.swift in Sources */, 1ADFF4C024CA6964006DC7AE /* URLBar.swift in Sources */, CDAD9CEA263A318F00FF7199 /* ShareableURL.swift in Sources */, @@ -776,7 +782,7 @@ CODE_SIGN_ENTITLEMENTS = "App/Supporting Files/SBrowser.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 5; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = DQQH5H6GBD; INFOPLIST_FILE = "App/Supporting Files/Info.plist"; @@ -811,7 +817,7 @@ CODE_SIGN_ENTITLEMENTS = "App/Supporting Files/SBrowser.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 5; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = DQQH5H6GBD; INFOPLIST_FILE = "App/Supporting Files/Info.plist";