From 8fe8426cc2a0bac49d0c42b6cbd04e95c8316a6b Mon Sep 17 00:00:00 2001 From: James Magahern Date: Mon, 5 May 2025 18:14:46 -0700 Subject: [PATCH] Delete web process bundle in favor of custom scheme handler --- ...BrowserViewController+WebKitDelegate.swift | 24 -- App/Hacks/MFMailComposeViewControllerFix.m | 24 ++ App/Supporting Files/SBrowser.entitlements | 4 - .../SBRProcessBundleBridge.h | 2 - .../SBRProcessBundleBridge.m | 211 +++++++++++------- SBrowser.xcodeproj/project.pbxproj | 143 +----------- SBrowserProcessBundle/Info.plist | 24 -- SBrowserProcessBundle/SBRProcessPlugin.h | 17 -- SBrowserProcessBundle/SBRProcessPlugin.m | 115 ---------- SBrowserProcessBundle/SBRWebProcessDelegate.h | 16 -- SBrowserProcessBundle/SBRWebProcessProxy.h | 29 --- 11 files changed, 162 insertions(+), 447 deletions(-) delete mode 100644 SBrowserProcessBundle/Info.plist delete mode 100644 SBrowserProcessBundle/SBRProcessPlugin.h delete mode 100644 SBrowserProcessBundle/SBRProcessPlugin.m delete mode 100644 SBrowserProcessBundle/SBRWebProcessDelegate.h delete mode 100644 SBrowserProcessBundle/SBRWebProcessProxy.h diff --git a/App/Browser View/BrowserViewController+WebKitDelegate.swift b/App/Browser View/BrowserViewController+WebKitDelegate.swift index 5fcb0da..79e6aa3 100644 --- a/App/Browser View/BrowserViewController+WebKitDelegate.swift +++ b/App/Browser View/BrowserViewController+WebKitDelegate.swift @@ -16,30 +16,6 @@ extension BrowserViewController: WKNavigationDelegate, WKUIDelegate tab.loadError = nil } - // Check to make sure we have connected to the web content process - if !currentTab.bridge.webContentProcessConnected { - // This means we started loading a page but the web content process hasn't loaded, which means - // scripts are not getting blocked. - - // If you're ad-hoc signing this, you'll need to disable library validation: - // sudo defaults write /Library/Preferences/com.apple.security.libraryvalidation DisableLibraryValidation -bool YES - - DispatchQueue.main.async { [unowned self] in - // Stop loading now - webView.stopLoading() - - // Show an alert - let alert = UIAlertController(title: "Web Process Not Loaded", - message: "The web content process never contacted the host application", - preferredStyle: .alert) - alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in - alert.dismiss(animated: true, completion: nil) - })) - - present(alert, animated: true, completion: nil) - } - } - // Reset tracking this currentTab.allowedScriptOrigins.removeAll() currentTab.blockedScriptOrigins.removeAll() diff --git a/App/Hacks/MFMailComposeViewControllerFix.m b/App/Hacks/MFMailComposeViewControllerFix.m index c8f0972..96880c2 100644 --- a/App/Hacks/MFMailComposeViewControllerFix.m +++ b/App/Hacks/MFMailComposeViewControllerFix.m @@ -7,6 +7,7 @@ #import #import +#import #import @interface MFMailComposeViewController (InternalMethods) @@ -31,3 +32,26 @@ static void swizzleMFMailComposeViewController(void) return YES; })); } + +@interface WKWebView (Hacks) ++ (BOOL)orig_handlesURLScheme:(NSString *)scheme; +@end + +@implementation WKWebView (Hacks) ++ (BOOL)orig_handlesURLScheme:(NSString *)scheme +{ + if ([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"]) { + return NO; + } + + return [self orig_handlesURLScheme:scheme]; +} +@end + +__attribute__((constructor)) +static void swizzleWebKitConfiguration(void) +{ + Method origMethod = class_getClassMethod(WKWebView.class, @selector(handlesURLScheme:)); + Method replMethod = class_getClassMethod(WKWebView.class, @selector(orig_handlesURLScheme:)); + method_exchangeImplementations(origMethod, replMethod); +} diff --git a/App/Supporting Files/SBrowser.entitlements b/App/Supporting Files/SBrowser.entitlements index 44b0952..ee95ab7 100644 --- a/App/Supporting Files/SBrowser.entitlements +++ b/App/Supporting Files/SBrowser.entitlements @@ -6,9 +6,5 @@ com.apple.security.network.client - com.apple.developer.web-browser - - com.apple.developer.device-information.user-assigned-device-name - diff --git a/App/Web Process Bundle Bridge/SBRProcessBundleBridge.h b/App/Web Process Bundle Bridge/SBRProcessBundleBridge.h index 0f6a693..4ca8564 100644 --- a/App/Web Process Bundle Bridge/SBRProcessBundleBridge.h +++ b/App/Web Process Bundle Bridge/SBRProcessBundleBridge.h @@ -36,8 +36,6 @@ NS_SWIFT_NAME(ProcessBundleBridge) @property (nonatomic, assign) BOOL allowAllScripts; // default is NO @property (nonatomic, assign) BOOL darkModeEnabled; -@property (nonatomic, readonly) BOOL webContentProcessConnected; - - (instancetype)initWithWebViewConfiguration:(nullable WKWebViewConfiguration *)webViewConfiguration NS_DESIGNATED_INITIALIZER; - (void)policyDataSourceDidChange; diff --git a/App/Web Process Bundle Bridge/SBRProcessBundleBridge.m b/App/Web Process Bundle Bridge/SBRProcessBundleBridge.m index 235a33b..1473a5a 100644 --- a/App/Web Process Bundle Bridge/SBRProcessBundleBridge.m +++ b/App/Web Process Bundle Bridge/SBRProcessBundleBridge.m @@ -7,8 +7,9 @@ #import "SBRProcessBundleBridge.h" -#import "SBRWebProcessDelegate.h" -#import "SBRWebProcessProxy.h" +#import "SBRScriptPolicy.h" + +#import #import #import @@ -20,21 +21,51 @@ #import #import -@interface SBRProcessBundleBridge () +#define LOG_DEBUG(format, ...) os_log_debug(_log, format, ##__VA_ARGS__) +#define LOG_ERROR(format, ...) os_log_error(_log, format, ##__VA_ARGS__) + +@interface NSURLResponse (BridgeAdditions) +@property (nonatomic, readonly) BOOL isJavascriptResponse; +@end + +@implementation NSURLResponse (BridgeAdditions) + +- (BOOL)isJavascriptResponse +{ + NSString *extension = [[self URL] pathExtension]; + if ([[extension lowercaseString] isEqualToString:@"js"]) { + return YES; + } + + NSString *MIMEType = [self MIMEType]; + if ([[MIMEType lowercaseString] containsString:@"javascript"]) { + return YES; + } + + return NO; +} + +@end + +@interface SBRProcessBundleBridge () @end @implementation SBRProcessBundleBridge { + os_log_t _log; + WKWebView *_webView; WKWebViewConfiguration *_webViewConfiguration; WKProcessPool *_processPool; - id _webProcessProxy; _WKUserStyleSheet *_darkModeStyleSheet; WKUserScript *_readabilityScript; NSArray *_userScripts; + dispatch_queue_t _dataTasksAccessQueue; + NSMutableDictionary *_dataTasks; + // These come from settings. _WKUserStyleSheet *_customizedUserStylesheet; WKUserScript *_customizedUserScript; @@ -42,29 +73,7 @@ - (void)tearDown { - [[_webView _remoteObjectRegistry] unregisterExportedObject:self interface:[self _webProcessDelegateInterface]]; -} - -- (_WKRemoteObjectInterface *)_webProcessDelegateInterface -{ - static dispatch_once_t onceToken; - static _WKRemoteObjectInterface *interface = nil; - dispatch_once(&onceToken, ^{ - interface = [_WKRemoteObjectInterface remoteObjectInterfaceWithProtocol:@protocol(SBRWebProcessDelegate)]; - }); - - return interface; -} - -- (_WKRemoteObjectInterface *)_webProcessProxyInterface -{ - static dispatch_once_t onceToken; - static _WKRemoteObjectInterface *interface = nil; - dispatch_once(&onceToken, ^{ - interface = [_WKRemoteObjectInterface remoteObjectInterfaceWithProtocol:@protocol(SBRWebProcessProxy)]; - }); - - return interface; + // This was used to unregister the delegate with the web process. } - (instancetype)initWithWebViewConfiguration:(WKWebViewConfiguration *)webViewConfiguration @@ -72,32 +81,22 @@ self = [super init]; if (self) { if (!webViewConfiguration) { + _log = os_log_create("net.buzzert.attractor.webview", "bridge"); + webViewConfiguration = [[WKWebViewConfiguration alloc] init]; - - // Inject bundle - _WKProcessPoolConfiguration *poolConfiguration = [[_WKProcessPoolConfiguration alloc] init]; - NSURL *bundleURL = [[[NSBundle mainBundle] builtInPlugInsURL] URLByAppendingPathComponent:@"SBrowserProcessBundle.bundle"]; - - // Make sure it exists. Bail if otherwise. - NSBundle *pluginBundle = [NSBundle bundleWithURL:bundleURL]; - NSAssert(pluginBundle != nil, @"Attix process bundle not found at %@", bundleURL.path); - - [poolConfiguration setInjectedBundleURL:bundleURL]; // Set up process pool - _processPool = [[WKProcessPool alloc] _initWithConfiguration:poolConfiguration]; - - // Initialize allowed origins now - NSDictionary *policies = [_policyDataSource scriptPolicyTypeByOrigin]; - NSArray *allowedOrigins = [[_policyDataSource allowedOriginsForScriptResources] allObjects]; - [_processPool _setObject:allowedOrigins forBundleParameter:SBRGetAllowedOriginsKey()]; - [_processPool _setObject:@(_allowAllScripts) forBundleParameter:SBRGetAllScriptsAllowedKey()]; - [_processPool _setObject:policies forBundleParameter:SBRGetPolicyTypeByOriginKey()]; - + _processPool = [[WKProcessPool alloc] init]; webViewConfiguration.processPool = _processPool; webViewConfiguration._waitsForPaintAfterViewDidMoveToWindow = NO; webViewConfiguration._applePayEnabled = YES; + + _dataTasks = [NSMutableDictionary dictionary]; + _dataTasksAccessQueue = dispatch_queue_create("net.buzzert.attractor.dataTasksAccess", DISPATCH_QUEUE_SERIAL); + + [webViewConfiguration setURLSchemeHandler:self forURLScheme:@"http"]; + [webViewConfiguration setURLSchemeHandler:self forURLScheme:@"https"]; } _webViewConfiguration = webViewConfiguration; @@ -117,12 +116,6 @@ webView.findInteractionEnabled = YES; } - // Configure proxy interface (interface to remote web process) - _webProcessProxy = [[webView _remoteObjectRegistry] remoteObjectProxyWithInterface:[self _webProcessProxyInterface]]; - - // Configure delegate interface (registering us as the web process delegate for the remote process) - [[webView _remoteObjectRegistry] registerExportedObject:self interface:[self _webProcessDelegateInterface]]; - _webView = webView; } @@ -172,45 +165,113 @@ } } -#pragma mark - -- (void)webProcessDidConnect -{ - NSLog(@"SBRProcessBundleBridge: did connect. Saying hello, syncing allowlist"); - _webContentProcessConnected = YES; - - [_webProcessProxy hello]; - [self policyDataSourceDidChange]; -} +#pragma mark Former methods - (void)webProcessDidAllowScriptWithOrigin:(NSString *)origin { - [[self delegate] webProcess:self didAllowScriptResourceFromOrigin:origin]; + dispatch_async(dispatch_get_main_queue(), ^{ + [[self delegate] webProcess:self didAllowScriptResourceFromOrigin:origin]; + }); } - (void)webProcessDidBlockScriptWithOrigin:(NSString *)origin { - [[self delegate] webProcess:self didBlockScriptResourceFromOrigin:origin]; + dispatch_async(dispatch_get_main_queue(), ^{ + [[self delegate] webProcess:self didBlockScriptResourceFromOrigin:origin]; + }); +} + +#pragma mark + +- (void)webView:(WKWebView *)webView startURLSchemeTask:(id)urlSchemeTask +{ + NSString *hostOrigin = [[_webView URL] host]; + NSURLRequest *request = [urlSchemeTask request]; + + LOG_DEBUG("Start URL scheme task: request: %@", request); + + __weak __auto_type welf = self; + NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) + { + if (!welf) return; + __strong __auto_type sself = welf; + + if (error != nil) { + [urlSchemeTask didFailWithError:error]; + } else if ([response isKindOfClass:[NSHTTPURLResponse class]]) { + NSURL *requestURL = [request URL]; + NSString *resourceOrigin = [requestURL host]; + const __auto_type allowResource = ^{ + os_log_debug(sself->_log, "Allowing resource: %@", requestURL.lastPathComponent); + [urlSchemeTask didReceiveResponse:response]; + [urlSchemeTask didReceiveData:data]; + [urlSchemeTask didFinish]; + + [self webProcessDidAllowScriptWithOrigin:resourceOrigin]; + }; + + const __auto_type denyResource = ^{ + os_log_debug(sself->_log, "Blocking resource: %@", requestURL.lastPathComponent); + NSHTTPURLResponse *altResponse = [[NSHTTPURLResponse alloc] initWithURL:requestURL + MIMEType:@"application/javascript" + expectedContentLength:0 textEncodingName:@"utf8"]; + [urlSchemeTask didReceiveResponse:altResponse]; + [urlSchemeTask didReceiveData:[NSData data]]; + [urlSchemeTask didFinish]; + + [self webProcessDidBlockScriptWithOrigin:resourceOrigin]; + }; + + // Check MIME type for JavaScript responses. + if ([response isJavascriptResponse] && ![sself allowAllScripts]) { + dispatch_async(sself->_dataTasksAccessQueue, ^{ + NSDictionary *policyTypes = [sself->_policyDataSource scriptPolicyTypeByOrigin]; + NSNumber *policyType = [policyTypes objectForKey:hostOrigin]; + + SBRScriptPolicy *policy = [[SBRScriptPolicy alloc] initWithSecurityOrigin:hostOrigin policyType:[policyType integerValue]]; + if ([policy allowsExternalJavaScriptResourceOrigin:resourceOrigin]) { + allowResource(); + } else { + denyResource(); + } + }); + } else { + allowResource(); + } + } else { + [urlSchemeTask didFailWithError:[NSError errorWithDomain:NSURLErrorDomain code:0 userInfo:nil]]; + } + + [sself->_dataTasks removeObjectForKey:request]; + }]; + + [_dataTasks setObject:dataTask forKey:request]; + [dataTask resume]; +} + +- (void)webView:(WKWebView *)webView stopURLSchemeTask:(id)urlSchemeTask +{ + NSURLRequest *request = [urlSchemeTask request]; + NSURLSessionDataTask *dataTask = [_dataTasks objectForKey:request]; + if (dataTask) { + if ([dataTask state] != NSURLSessionTaskStateCanceling) { + [dataTask cancel]; + } + + [_dataTasks removeObjectForKey:request]; + } } #pragma mark Actions - (void)policyDataSourceDidChange { - NSArray *allowedOrigins = [[_policyDataSource allowedOriginsForScriptResources] allObjects]; - [_processPool _setObject:allowedOrigins forBundleParameter:SBRGetAllowedOriginsKey()]; - [_webProcessProxy syncAllowedResourceOrigins:allowedOrigins]; - - NSDictionary *policyTypes = [_policyDataSource scriptPolicyTypeByOrigin]; - [_processPool _setObject:policyTypes forBundleParameter:SBRGetPolicyTypeByOriginKey()]; - [_webProcessProxy syncPolicyTypes:policyTypes]; + // This was used when we had to signal the process bundle. } - (void)setAllowAllScripts:(BOOL)allowAllScripts { _allowAllScripts = allowAllScripts; - [_processPool _setObject:@(_allowAllScripts) forBundleParameter:SBRGetAllScriptsAllowedKey()]; - [_webProcessProxy setAllScriptsAllowed:allowAllScripts]; } - (void)setDarkModeEnabled:(BOOL)darkModeEnabled @@ -232,7 +293,6 @@ } } - - (void)parseDocumentForReaderMode:(void (^)(NSString * _Nonnull))completionBlock { WKUserContentController *userContentController = [_webViewConfiguration userContentController]; @@ -248,9 +308,10 @@ "var article = new Readability(documentClone).parse();" "article.content"; + os_log_t log = _log; [_webView evaluateJavaScript:script completionHandler:^(NSString *result, NSError * _Nullable error) { if (error != nil) { - NSLog(@"Bridge: Readability error: %@", error.localizedDescription); + os_log_error(log, "Bridge: Readability error: %@", error.localizedDescription); } else { completionBlock(result); } diff --git a/SBrowser.xcodeproj/project.pbxproj b/SBrowser.xcodeproj/project.pbxproj index 9c88823..05384c2 100644 --- a/SBrowser.xcodeproj/project.pbxproj +++ b/SBrowser.xcodeproj/project.pbxproj @@ -27,10 +27,7 @@ 1ADFF46C24C7DE54006DC7AE /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1ADFF46A24C7DE54006DC7AE /* LaunchScreen.storyboard */; }; 1ADFF47424C7DE9C006DC7AE /* BrowserViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ADFF47324C7DE9C006DC7AE /* BrowserViewController.swift */; }; 1ADFF47924C7DFF8006DC7AE /* BrowserView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ADFF47824C7DFF8006DC7AE /* BrowserView.swift */; }; - 1ADFF48424C8C12F006DC7AE /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1ADFF48324C8C12F006DC7AE /* Foundation.framework */; }; 1ADFF48D24C8C176006DC7AE /* SBRProcessBundleBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 1ADFF48C24C8C176006DC7AE /* SBRProcessBundleBridge.m */; }; - 1ADFF4A724C8C271006DC7AE /* SBrowserProcessBundle.bundle in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 1ADFF48124C8C12F006DC7AE /* SBrowserProcessBundle.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 1ADFF4AA24C8D477006DC7AE /* SBRProcessPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 1ADFF4A924C8D477006DC7AE /* SBRProcessPlugin.m */; }; 1ADFF4AE24C8ED32006DC7AE /* ResourcePolicyManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ADFF4AD24C8ED32006DC7AE /* ResourcePolicyManager.swift */; }; 1ADFF4C024CA6964006DC7AE /* URLBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ADFF4BF24CA6964006DC7AE /* URLBar.swift */; }; 1ADFF4C324CA6AF6006DC7AE /* Geometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ADFF4C224CA6AF6006DC7AE /* Geometry.swift */; }; @@ -63,7 +60,6 @@ CD936A3B289DB3380093A1AC /* TabInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD936A3A289DB3380093A1AC /* TabInfo.swift */; }; CD936A3D289DB88B0093A1AC /* UIView+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD936A3C289DB88B0093A1AC /* UIView+Utils.swift */; }; CD97CF9225D5BE6F00288FEE /* NavigationControlsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD97CF9125D5BE6F00288FEE /* NavigationControlsView.swift */; }; - CD9B88C2272201E900DAAB7E /* SBRScriptPolicy.m in Sources */ = {isa = PBXBuildFile; fileRef = CD361CF5271A3718006E9CA5 /* SBRScriptPolicy.m */; }; CDACE18C2C5B09F00053AB29 /* StringUtilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDACE18B2C5B09F00053AB29 /* StringUtilities.swift */; }; CDAD9CE8263A2DF200FF7199 /* DocumentControlsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDAD9CE7263A2DF200FF7199 /* DocumentControlsView.swift */; }; CDAD9CEA263A318F00FF7199 /* ShareableURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDAD9CE9263A318F00FF7199 /* ShareableURL.swift */; }; @@ -87,16 +83,6 @@ CDF34690276C14BD00FB3141 /* CodeEditorSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDF3468F276C14BD00FB3141 /* CodeEditorSettingsViewController.swift */; }; /* End PBXBuildFile section */ -/* Begin PBXContainerItemProxy section */ - 1ADFF48E24C8C230006DC7AE /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 1ADFF45424C7DE53006DC7AE /* Project object */; - proxyType = 1; - remoteGlobalIDString = 1ADFF48024C8C12F006DC7AE; - remoteInfo = SBrowserProcessBundle; - }; -/* End PBXContainerItemProxy section */ - /* Begin PBXCopyFilesBuildPhase section */ 1ADFF4A124C8C25B006DC7AE /* Embed App Extensions */ = { isa = PBXCopyFilesBuildPhase; @@ -104,7 +90,6 @@ dstPath = ""; dstSubfolderSpec = 13; files = ( - 1ADFF4A724C8C271006DC7AE /* SBrowserProcessBundle.bundle in Embed App Extensions */, ); name = "Embed App Extensions"; runOnlyForDeploymentPostprocessing = 0; @@ -135,16 +120,10 @@ 1ADFF47324C7DE9C006DC7AE /* BrowserViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserViewController.swift; sourceTree = ""; }; 1ADFF47524C7DF20006DC7AE /* SBrowser.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SBrowser.entitlements; sourceTree = ""; }; 1ADFF47824C7DFF8006DC7AE /* BrowserView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserView.swift; sourceTree = ""; }; - 1ADFF48124C8C12F006DC7AE /* SBrowserProcessBundle.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SBrowserProcessBundle.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; 1ADFF48324C8C12F006DC7AE /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 1ADFF48624C8C12F006DC7AE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 1ADFF48A24C8C176006DC7AE /* SBrowser-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SBrowser-Bridging-Header.h"; sourceTree = ""; }; 1ADFF48B24C8C176006DC7AE /* SBRProcessBundleBridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SBRProcessBundleBridge.h; sourceTree = ""; }; 1ADFF48C24C8C176006DC7AE /* SBRProcessBundleBridge.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SBRProcessBundleBridge.m; sourceTree = ""; }; - 1ADFF4A824C8D476006DC7AE /* SBRProcessPlugin.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SBRProcessPlugin.h; sourceTree = ""; }; - 1ADFF4A924C8D477006DC7AE /* SBRProcessPlugin.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SBRProcessPlugin.m; sourceTree = ""; }; - 1ADFF4AB24C8DF62006DC7AE /* SBRWebProcessDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SBRWebProcessDelegate.h; sourceTree = ""; }; - 1ADFF4AC24C8DFEE006DC7AE /* SBRWebProcessProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SBRWebProcessProxy.h; sourceTree = ""; }; 1ADFF4AD24C8ED32006DC7AE /* ResourcePolicyManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResourcePolicyManager.swift; sourceTree = ""; }; 1ADFF4BF24CA6964006DC7AE /* URLBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLBar.swift; sourceTree = ""; }; 1ADFF4C224CA6AF6006DC7AE /* Geometry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Geometry.swift; sourceTree = ""; }; @@ -214,14 +193,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 1ADFF47E24C8C12F006DC7AE /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 1ADFF48424C8C12F006DC7AE /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -288,7 +259,6 @@ children = ( CDB6808828B4569F007D787E /* LICENSE.txt */, 1ADFF45E24C7DE53006DC7AE /* App */, - 1ADFF48524C8C12F006DC7AE /* SBrowserProcessBundle */, CDB73F3F2DA9F2F100DF4FAB /* WebKit Headers */, 1ADFF48224C8C12F006DC7AE /* Frameworks */, 1ADFF45D24C7DE53006DC7AE /* Products */, @@ -299,7 +269,6 @@ isa = PBXGroup; children = ( 1ADFF45C24C7DE53006DC7AE /* Attractor.app */, - 1ADFF48124C8C12F006DC7AE /* SBrowserProcessBundle.bundle */, ); name = Products; sourceTree = ""; @@ -374,18 +343,6 @@ name = Frameworks; sourceTree = ""; }; - 1ADFF48524C8C12F006DC7AE /* SBrowserProcessBundle */ = { - isa = PBXGroup; - children = ( - 1ADFF48624C8C12F006DC7AE /* Info.plist */, - 1ADFF4AB24C8DF62006DC7AE /* SBRWebProcessDelegate.h */, - 1ADFF4AC24C8DFEE006DC7AE /* SBRWebProcessProxy.h */, - 1ADFF4A824C8D476006DC7AE /* SBRProcessPlugin.h */, - 1ADFF4A924C8D477006DC7AE /* SBRProcessPlugin.m */, - ); - path = SBrowserProcessBundle; - sourceTree = ""; - }; 1ADFF4AF24C92E2F006DC7AE /* Web Process Bundle Bridge */ = { isa = PBXGroup; children = ( @@ -543,30 +500,12 @@ buildRules = ( ); dependencies = ( - 1ADFF48F24C8C230006DC7AE /* PBXTargetDependency */, ); name = App; productName = SBrowser; productReference = 1ADFF45C24C7DE53006DC7AE /* Attractor.app */; productType = "com.apple.product-type.application"; }; - 1ADFF48024C8C12F006DC7AE /* SBrowserProcessBundle */ = { - isa = PBXNativeTarget; - buildConfigurationList = 1ADFF48724C8C12F006DC7AE /* Build configuration list for PBXNativeTarget "SBrowserProcessBundle" */; - buildPhases = ( - 1ADFF47D24C8C12F006DC7AE /* Sources */, - 1ADFF47E24C8C12F006DC7AE /* Frameworks */, - 1ADFF47F24C8C12F006DC7AE /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = SBrowserProcessBundle; - productName = SBrowserProcessBundle; - productReference = 1ADFF48124C8C12F006DC7AE /* SBrowserProcessBundle.bundle */; - productType = "com.apple.product-type.bundle"; - }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -580,9 +519,6 @@ CreatedOnToolsVersion = 12.0; LastSwiftMigration = 1200; }; - 1ADFF48024C8C12F006DC7AE = { - CreatedOnToolsVersion = 12.0; - }; }; }; buildConfigurationList = 1ADFF45724C7DE53006DC7AE /* Build configuration list for PBXProject "SBrowser" */; @@ -599,7 +535,6 @@ projectRoot = ""; targets = ( 1ADFF45B24C7DE53006DC7AE /* App */, - 1ADFF48024C8C12F006DC7AE /* SBrowserProcessBundle */, ); }; /* End PBXProject section */ @@ -620,13 +555,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 1ADFF47F24C8C12F006DC7AE /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -703,25 +631,8 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 1ADFF47D24C8C12F006DC7AE /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - CD9B88C2272201E900DAAB7E /* SBRScriptPolicy.m in Sources */, - 1ADFF4AA24C8D477006DC7AE /* SBRProcessPlugin.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXSourcesBuildPhase section */ -/* Begin PBXTargetDependency section */ - 1ADFF48F24C8C230006DC7AE /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 1ADFF48024C8C12F006DC7AE /* SBrowserProcessBundle */; - targetProxy = 1ADFF48E24C8C230006DC7AE /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - /* Begin PBXVariantGroup section */ 1ADFF46A24C7DE54006DC7AE /* LaunchScreen.storyboard */ = { isa = PBXVariantGroup; @@ -881,7 +792,7 @@ PRODUCT_NAME = Attractor; PROVISIONING_PROFILE_SPECIFIER = ""; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; - SUPPORTS_MACCATALYST = NO; + SUPPORTS_MACCATALYST = YES; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; SWIFT_OBJC_BRIDGING_HEADER = "App/Supporting Files/SBrowser-Bridging-Header.h"; @@ -916,7 +827,7 @@ PRODUCT_NAME = Attractor; PROVISIONING_PROFILE_SPECIFIER = ""; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; - SUPPORTS_MACCATALYST = NO; + SUPPORTS_MACCATALYST = YES; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; SWIFT_OBJC_BRIDGING_HEADER = "App/Supporting Files/SBrowser-Bridging-Header.h"; @@ -925,47 +836,6 @@ }; name = Release; }; - 1ADFF48824C8C12F006DC7AE /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; - DEAD_CODE_STRIPPING = YES; - DEVELOPMENT_TEAM = DQQH5H6GBD; - INFOPLIST_FILE = SBrowserProcessBundle/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; - PRODUCT_BUNDLE_IDENTIFIER = net.buzzert.SBrowserProcessBundle; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - SKIP_INSTALL = YES; - STRIP_INSTALLED_PRODUCT = NO; - SUPPORTS_MACCATALYST = YES; - SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; - TARGETED_DEVICE_FAMILY = "1,2,6"; - WRAPPER_EXTENSION = bundle; - }; - name = Debug; - }; - 1ADFF48924C8C12F006DC7AE /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; - DEAD_CODE_STRIPPING = YES; - DEVELOPMENT_TEAM = DQQH5H6GBD; - INFOPLIST_FILE = SBrowserProcessBundle/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; - PRODUCT_BUNDLE_IDENTIFIER = net.buzzert.SBrowserProcessBundle; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - SKIP_INSTALL = YES; - SUPPORTS_MACCATALYST = YES; - SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; - TARGETED_DEVICE_FAMILY = "1,2,6"; - WRAPPER_EXTENSION = bundle; - }; - name = Release; - }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -987,15 +857,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 1ADFF48724C8C12F006DC7AE /* Build configuration list for PBXNativeTarget "SBrowserProcessBundle" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 1ADFF48824C8C12F006DC7AE /* Debug */, - 1ADFF48924C8C12F006DC7AE /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; /* End XCConfigurationList section */ /* Begin XCVersionGroup section */ diff --git a/SBrowserProcessBundle/Info.plist b/SBrowserProcessBundle/Info.plist deleted file mode 100644 index 3c9d48e..0000000 --- a/SBrowserProcessBundle/Info.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - $(PRODUCT_BUNDLE_PACKAGE_TYPE) - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - NSPrincipalClass - SBRProcessPlugin - - diff --git a/SBrowserProcessBundle/SBRProcessPlugin.h b/SBrowserProcessBundle/SBRProcessPlugin.h deleted file mode 100644 index 63077ce..0000000 --- a/SBrowserProcessBundle/SBRProcessPlugin.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// SBRProcessPlugin.h -// SBrowserProcessBundle -// -// Created by James Magahern on 7/22/20. -// - -#import -#import "WKWebProcessPlugIn.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface SBRProcessPlugin : NSObject - -@end - -NS_ASSUME_NONNULL_END diff --git a/SBrowserProcessBundle/SBRProcessPlugin.m b/SBrowserProcessBundle/SBRProcessPlugin.m deleted file mode 100644 index eca2a93..0000000 --- a/SBrowserProcessBundle/SBRProcessPlugin.m +++ /dev/null @@ -1,115 +0,0 @@ -// -// SBRProcessPlugin.m -// SBrowserProcessBundle -// -// Created by James Magahern on 7/22/20. -// - -#import "SBRProcessPlugin.h" - -#import "SBRWebProcessDelegate.h" -#import "SBRWebProcessProxy.h" -#import "SBRScriptPolicy.h" - -#import -#import -#import -#import -#import -#import - -@interface SBRProcessPlugin () - -@property (nonatomic, strong) id processDelegate; - -@property (nonatomic, assign) BOOL allScriptsAllowed; -@property (nonatomic, strong) NSMutableSet *allowedResourceOrigins; -@property (nonatomic, strong) NSDictionary *policyTypeByOrigin; -@end - -@implementation SBRProcessPlugin - -+ (void)initialize -{ - [super initialize]; - NSLog(@"SBRProcessPlugin Initialized"); -} - -#pragma mark - -- (void)hello -{ - NSLog(@"SBRProcessPlugin: Helloooooo"); -} - -- (void)syncAllowedResourceOrigins:(NSArray *)allowedOrigins -{ - _allowedResourceOrigins = [NSMutableSet setWithArray:allowedOrigins]; -} - -- (void)syncPolicyTypes:(NSDictionary *)policyTypes -{ - _policyTypeByOrigin = policyTypes; -} - -- (void)setAllScriptsAllowed:(BOOL)allScriptsAllowed -{ - _allScriptsAllowed = allScriptsAllowed; -} - -#pragma mark - -- (void)webProcessPlugIn:(WKWebProcessPlugInController *)plugInController initializeWithObject:(id)initializationObject -{ - _allowedResourceOrigins = [[plugInController parameters] valueForKey:SBRGetAllowedOriginsKey()]; - _allScriptsAllowed = [[[plugInController parameters] valueForKey:SBRGetAllScriptsAllowedKey()] boolValue]; - _policyTypeByOrigin = [[plugInController parameters] valueForKey:SBRGetPolicyTypeByOriginKey()]; - NSLog(@"SBRProcessPlugin: %lu origins allowed, all scripts allowed: %@ ", (unsigned long)_allowedResourceOrigins.count, _allScriptsAllowed ? @"YES" : @"NO"); -} - -- (void)webProcessPlugIn:(WKWebProcessPlugInController *)plugInController didCreateBrowserContextController:(WKWebProcessPlugInBrowserContextController *)browserContextController -{ - _WKRemoteObjectInterface *proxyInterface = [_WKRemoteObjectInterface remoteObjectInterfaceWithProtocol:@protocol(SBRWebProcessProxy)]; - [browserContextController._remoteObjectRegistry registerExportedObject:self interface:proxyInterface]; - - _WKRemoteObjectInterface *eventListenerInterface = [_WKRemoteObjectInterface remoteObjectInterfaceWithProtocol:@protocol(SBRWebProcessDelegate)]; - self.processDelegate = [browserContextController._remoteObjectRegistry remoteObjectProxyWithInterface:eventListenerInterface]; - - browserContextController.loadDelegate = self; - - [[self processDelegate] webProcessDidConnect]; -} - -#pragma mark - -- (NSURLRequest *)webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController *)controller frame:(WKWebProcessPlugInFrame *)frame willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse -{ - NSLog(@"SBRProcessPlugin: Sending request: %@", request); - if (_allowedResourceOrigins == nil) { - NSLog(@"Allowed resource origins should not be nil!!!!"); - } - - NSURL *requestURL = [request URL]; - NSString *resourceOrigin = [requestURL host]; - NSString *requestExtension = [requestURL pathExtension]; - NSString *hostOrigin = [[[controller mainFrame] URL] host]; - if (requestExtension.length > 0 && [requestExtension isEqualToString:@"js"]) { - NSNumber *policyType = [_policyTypeByOrigin objectForKey:hostOrigin]; - NSLog(@"SBRProcessPlugin: Policy type for %@: %@", hostOrigin, policyType); - - SBRScriptPolicy *policy = [[SBRScriptPolicy alloc] initWithSecurityOrigin:hostOrigin policyType:[policyType integerValue]]; - if ([self allScriptsAllowed] || [policy allowsExternalJavaScriptResourceOrigin:resourceOrigin]) { - NSLog(@"SBRProcessPlugin: Policy allows script requestURL: %@", requestURL); - [[self processDelegate] webProcessDidAllowScriptWithOrigin:resourceOrigin]; - } else { - NSLog(@"SBRProcessPlugin: Policy disallows script requestURL: %@", requestURL); - [[self processDelegate] webProcessDidBlockScriptWithOrigin:resourceOrigin]; - - request = nil; - } - } - - return request; -} - -@end diff --git a/SBrowserProcessBundle/SBRWebProcessDelegate.h b/SBrowserProcessBundle/SBRWebProcessDelegate.h deleted file mode 100644 index d0730b1..0000000 --- a/SBrowserProcessBundle/SBRWebProcessDelegate.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// SBRWebProcessDelegate.h -// SBrowser -// -// Created by James Magahern on 7/22/20. -// - -#import - -@protocol SBRWebProcessDelegate - -- (void)webProcessDidConnect; -- (void)webProcessDidBlockScriptWithOrigin:(NSString *)origin; -- (void)webProcessDidAllowScriptWithOrigin:(NSString *)origin; - -@end diff --git a/SBrowserProcessBundle/SBRWebProcessProxy.h b/SBrowserProcessBundle/SBRWebProcessProxy.h deleted file mode 100644 index 981080f..0000000 --- a/SBrowserProcessBundle/SBRWebProcessProxy.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// SBRWebProcessProxy.h -// SBrowser -// -// Created by James Magahern on 7/22/20. -// - -#import - -static inline NSString* SBRGetAllowedOriginsKey(void) { - return @"allowedOrigins"; -} - -static inline NSString* SBRGetAllScriptsAllowedKey(void) { - return @"allScriptsAllowed"; -} - -static inline NSString* SBRGetPolicyTypeByOriginKey(void) { - return @"policyTypeByOrigin"; -} - -@protocol SBRWebProcessProxy - -- (void)hello; -- (void)setAllScriptsAllowed:(BOOL)allowed; -- (void)syncAllowedResourceOrigins:(NSArray *)allowedOrigins; -- (void)syncPolicyTypes:(NSDictionary *)policyTypes; - -@end