From 9f4e14099c4634611df394be558ae14dfb90f016 Mon Sep 17 00:00:00 2001 From: Benjamin Erhart Date: Tue, 12 Mar 2019 17:10:32 +0100 Subject: [PATCH 01/18] Replaced deprecated UISearchDisplayController with new UISearchController. --- Endless/RuleEditorController.h | 3 +- Endless/RuleEditorController.m | 95 ++++++++++++++++++++-------------- 2 files changed, 57 insertions(+), 41 deletions(-) diff --git a/Endless/RuleEditorController.h b/Endless/RuleEditorController.h index ba9bacc..df12f6d 100644 --- a/Endless/RuleEditorController.h +++ b/Endless/RuleEditorController.h @@ -9,13 +9,12 @@ #import "AppDelegate.h" #import "RuleEditorRow.h" -@interface RuleEditorController : UITableViewController +@interface RuleEditorController : UITableViewController @property AppDelegate *appDelegate; @property NSMutableArray *sortedRuleRows; @property NSMutableArray *inUseRuleRows; -@property UISearchBar *searchBar; @property NSMutableArray *searchResult; - (NSString *)ruleDisabledReason:(RuleEditorRow *)row; diff --git a/Endless/RuleEditorController.m b/Endless/RuleEditorController.m index abaec6d..5b7e19c 100644 --- a/Endless/RuleEditorController.m +++ b/Endless/RuleEditorController.m @@ -9,7 +9,7 @@ @implementation RuleEditorController -UISearchDisplayController *searchDisplayController; +UISearchController *searchController; - (id)initWithStyle:(UITableViewStyle)style { @@ -29,19 +29,17 @@ - (void)viewDidLoad { [super viewDidLoad]; - self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)]; - - searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:self.searchBar contentsController:self]; - searchDisplayController.delegate = self; - searchDisplayController.searchResultsDataSource = self; - searchDisplayController.searchResultsTableView.delegate = self; + searchController = [[UISearchController alloc] initWithSearchResultsController:nil]; + searchController.searchResultsUpdater = self; + searchController.obscuresBackgroundDuringPresentation = NO; + self.definesPresentationContext = YES; + self.navigationItem.searchController = searchController; self.tableView.delegate = self; - - [[self tableView] setTableHeaderView:self.searchBar]; } -#pragma mark - Table view data source + +#pragma mark - UITableViewDataSource - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { @@ -60,7 +58,7 @@ - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger { if (section == 0) return [self.inUseRuleRows count]; - else if (tableView == self.searchDisplayController.searchResultsTableView) + else if ([self isFiltering]) return [self.searchResult count]; else return [self.sortedRuleRows count]; @@ -121,18 +119,36 @@ - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEd [tableView reloadData]; } + +#pragma mark - UITableViewDelegate + - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:YES]; } -- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString +- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(nonnull NSIndexPath *)indexPath +{ + RuleEditorRow *row = [self ruleForTableView:tableView atIndexPath:indexPath]; + + if ([self ruleDisabledReason:row] == nil) + return NSLocalizedString(@"Disable", nil); + else + return NSLocalizedString(@"Enable", nil); +} + + +# pragma mark - UISearchResultsUpdating + +- (void)updateSearchResultsForSearchController:(UISearchController *)searchController { + NSString *search = searchController.searchBar.text; + [self.searchResult removeAllObjects]; - + for (RuleEditorRow *row in self.sortedRuleRows) { if ([row textLabel] != nil) { - NSRange range = [[row textLabel] rangeOfString:searchString options:NSCaseInsensitiveSearch]; + NSRange range = [[row textLabel] rangeOfString:search options:NSCaseInsensitiveSearch]; if (range.length > 0) { [self.searchResult addObject:row]; @@ -140,58 +156,59 @@ - (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldRe } } if ([row detailTextLabel] != nil) { - NSRange range = [[row detailTextLabel] rangeOfString:searchString options:NSCaseInsensitiveSearch]; - + NSRange range = [[row detailTextLabel] rangeOfString:search options:NSCaseInsensitiveSearch]; + if (range.length > 0) { [self.searchResult addObject:row]; continue; } } } - - return YES; + + [self.tableView reloadData]; } -- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(nonnull NSIndexPath *)indexPath + +# pragma mark - Public Methods + +- (NSString *)ruleDisabledReason:(RuleEditorRow *)row { - RuleEditorRow *row = [self ruleForTableView:tableView atIndexPath:indexPath]; + return nil; +} - if ([self ruleDisabledReason:row] == nil) - return NSLocalizedString(@"Disable", nil); - else - return NSLocalizedString(@"Enable", nil); +- (void)disableRuleForRow:(RuleEditorRow *)row withReason:(NSString *)reason +{ + abort(); } +- (void)enableRuleForRow:(RuleEditorRow *)row +{ + abort(); +} + + +# pragma mark - Private Methods + - (RuleEditorRow *)ruleForTableView:(UITableView *)tableView atIndexPath:(NSIndexPath *)indexPath { NSMutableArray *group; - + if ([indexPath section] == 0) group = [self inUseRuleRows]; - else if (tableView == self.searchDisplayController.searchResultsTableView) + else if ([self isFiltering]) group = [self searchResult]; else group = [self sortedRuleRows]; - + if (group && [group count] > [indexPath row]) return [group objectAtIndex:indexPath.row]; else return nil; } -- (NSString *)ruleDisabledReason:(RuleEditorRow *)row +- (BOOL)isFiltering { - return nil; -} - -- (void)disableRuleForRow:(RuleEditorRow *)row withReason:(NSString *)reason -{ - abort(); -} - -- (void)enableRuleForRow:(RuleEditorRow *)row -{ - abort(); + return searchController.isActive && searchController.searchBar.text.length != 0; } @end From 52b95988260003e5615988224eb4b650f04728d4 Mon Sep 17 00:00:00 2001 From: joshua stein Date: Mon, 18 Mar 2019 12:50:49 -0500 Subject: [PATCH 02/18] README: endless is no longer in the App Store --- README.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/README.md b/README.md index 98cbe21..0a17692 100644 --- a/README.md +++ b/README.md @@ -3,11 +3,6 @@ An open-source MobileSafari-like web browser for iOS ([wrapping around UIWebView](#infrequently-asked-questions)) with a design goal of increased security and privacy. -Current builds are available for free in the -[App Store](https://itunes.apple.com/us/app/endless-browser/id974745755?mt=8) -and include (completely optional) in-app purchases to contribute to the funding -of continued development. - While this software is open source and you are free to modify it and use it on your own devices, redistribution of this software in binary form, with or without modification, is not permitted. From 803b52ca97cc978ccebf43c71220e79f8c779d77 Mon Sep 17 00:00:00 2001 From: Benjamin Erhart Date: Fri, 22 Mar 2019 15:19:43 +0100 Subject: [PATCH 03/18] Allow automatic size adjustment of menu labels. Important for translations. --- Endless/WebViewMenuController.m | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Endless/WebViewMenuController.m b/Endless/WebViewMenuController.m index 88ab247..da8ad78 100644 --- a/Endless/WebViewMenuController.m +++ b/Endless/WebViewMenuController.m @@ -97,6 +97,12 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N cell.detailTextLabel.text = nil; cell.detailTextLabel.font = [UIFont systemFontOfSize:11]; + // Allow auto-adjustment for translations. + cell.textLabel.adjustsFontSizeToFitWidth = YES; + cell.textLabel.minimumScaleFactor = .5; + cell.detailTextLabel.adjustsFontSizeToFitWidth = YES; + cell.detailTextLabel.minimumScaleFactor = .5; + if ([[appDelegate webViewController] darkInterface]) { cell.textLabel.textColor = [UIColor colorWithRed:0.8 green:0.8 blue:0.8 alpha:1.0]; cell.detailTextLabel.textColor = [UIColor grayColor]; From 1c5a84509a08995336ebd9b6daaeb0f27069ca49 Mon Sep 17 00:00:00 2001 From: Benjamin Erhart Date: Fri, 22 Mar 2019 15:23:18 +0100 Subject: [PATCH 04/18] Fixed stupid translation. --- Endless/de.lproj/Localizable.strings | Bin 20768 -> 20766 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Endless/de.lproj/Localizable.strings b/Endless/de.lproj/Localizable.strings index 80ba279a18056b8e050699bff0cbe5d3cbfeb7ce..28e13aeb7f893f896abab5129f6e7910c4d0dfda 100644 GIT binary patch delta 20 ccmZ3mh;iN`#tj~Nto{sX3~8JF^)4y_08Fz6?f?J) delta 22 ccmbQYh;hLp#tj~N?AI95fG}^fuiix^0AD=^;{X5v From 5e58b4eb9bcf758334009f7aecf36d96e69e8333 Mon Sep 17 00:00:00 2001 From: Benjamin Erhart Date: Fri, 22 Mar 2019 16:24:03 +0100 Subject: [PATCH 05/18] Silence deprecation warnings about stuff (esp. UIWebView) this app is inevitably built around. --- Endless.xcodeproj/project.pbxproj | 2 ++ Endless/HostSettingsController.m | 4 ++++ Endless/SilenceDeprecation.h | 29 +++++++++++++++++++++++++++++ Endless/WebViewController.m | 2 ++ Endless/WebViewTab.h | 3 +++ Endless/WebViewTab.m | 22 ++++++++++++++++++++-- External/CKHTTPConnection.m | 16 ++++++++++------ External/OnePasswordExtension.m | 18 ++++++++++++++++-- 8 files changed, 86 insertions(+), 10 deletions(-) create mode 100644 Endless/SilenceDeprecation.h diff --git a/Endless.xcodeproj/project.pbxproj b/Endless.xcodeproj/project.pbxproj index 8dea763..4c47c80 100644 --- a/Endless.xcodeproj/project.pbxproj +++ b/Endless.xcodeproj/project.pbxproj @@ -241,6 +241,7 @@ A024D5AD1ECEF10F00B28CC5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Endless/Base.lproj/OnePasswordExtension.strings; sourceTree = ""; }; A024D5B01ECEF11A00B28CC5 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = Endless/de.lproj/Localizable.strings; sourceTree = ""; }; A024D5B11ECEF11A00B28CC5 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = Endless/de.lproj/OnePasswordExtension.strings; sourceTree = ""; }; + A07E147222381A8700B76F77 /* SilenceDeprecation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SilenceDeprecation.h; sourceTree = ""; }; FC10255E5E506A0C25D6276B /* libPods-Endless Tests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Endless Tests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; FDEC322B35C8D861612E24E3 /* Pods-Endless Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Endless Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Endless Tests/Pods-Endless Tests.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -372,6 +373,7 @@ 013E71CF1E5150C000BB0572 /* urlblocker.json */, 015748031E208C5000DB2044 /* UIResponder+FirstResponder.h */, 015748041E208C5000DB2044 /* UIResponder+FirstResponder.m */, + A07E147222381A8700B76F77 /* SilenceDeprecation.h */, ); name = "Supporting Files"; path = Endless; diff --git a/Endless/HostSettingsController.m b/Endless/HostSettingsController.m index 67aecae..2392312 100644 --- a/Endless/HostSettingsController.m +++ b/Endless/HostSettingsController.m @@ -9,7 +9,11 @@ #import "HostSettings.h" #import "HostSettingsController.h" +#import "SilenceDeprecation.h" + +SILENCE_DEPRECATION_ON #import "XLForm.h" +SILENCE_DEPRECATION_OFF @interface HostSettingsXLFormViewController : XLFormViewController @property (copy, nonatomic) void (^disappearCallback)(HostSettingsXLFormViewController *); diff --git a/Endless/SilenceDeprecation.h b/Endless/SilenceDeprecation.h new file mode 100644 index 0000000..62f1ae0 --- /dev/null +++ b/Endless/SilenceDeprecation.h @@ -0,0 +1,29 @@ +// +// SilenceDeprecation.h +// Endless +// +// Created by Benjamin Erhart on 12.03.19. +// Copyright © 2019 jcs. All rights reserved. +// + +#ifndef SilenceDeprecation_h +#define SilenceDeprecation_h + +#define SILENCE_DEPRECATION_ON \ +_Pragma("clang diagnostic push") \ +_Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") \ +_Pragma("clang diagnostic ignored \"-Wdeprecated-implementations\"") + +#define SILENCE_DEPRECATION_OFF \ +_Pragma("clang diagnostic pop") + +#define SILENCE_DEPRECATION(expr) \ +do { \ +_Pragma("clang diagnostic push") \ +_Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") \ +_Pragma("clang diagnostic ignored \"-Wdeprecated-implementations\"") \ +expr; \ +_Pragma("clang diagnostic pop") \ +} while(0) + +#endif /* SilenceDeprecation_h */ diff --git a/Endless/WebViewController.m b/Endless/WebViewController.m index d4ec256..941895f 100644 --- a/Endless/WebViewController.m +++ b/Endless/WebViewController.m @@ -1218,7 +1218,9 @@ - (NSString *)buildDefaultUserAgent * to "Mozilla/5.0 (iPhone; CPU iPhone OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12H321 Safari/600.1.4" */ + SILENCE_DEPRECATION_ON UIWebView *twv = [[UIWebView alloc] initWithFrame:CGRectZero]; + SILENCE_DEPRECATION_OFF NSString *ua = [twv stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"]; NSMutableArray *uapieces = [[NSMutableArray alloc] initWithArray:[ua componentsSeparatedByString:@" "]]; diff --git a/Endless/WebViewTab.h b/Endless/WebViewTab.h index c61a89d..2e2a117 100644 --- a/Endless/WebViewTab.h +++ b/Endless/WebViewTab.h @@ -9,6 +9,7 @@ #import #import "SSLCertificate.h" +#import "SilenceDeprecation.h" #define ZOOM_OUT_SCALE 0.8 #define ZOOM_OUT_SCALE_ROTATED 0.7 @@ -99,7 +100,9 @@ static const struct keyboard_map_entry { @interface WebViewTab : NSObject @property (strong, atomic) UIView *viewHolder; +SILENCE_DEPRECATION_ON @property (strong, atomic) UIWebView *webView; +SILENCE_DEPRECATION_OFF @property (strong, atomic) UIRefreshControl *refresher; @property (strong, atomic) NSURL *url; @property BOOL needsRefresh; diff --git a/Endless/WebViewTab.m b/Endless/WebViewTab.m index bfa8285..41c2c42 100644 --- a/Endless/WebViewTab.m +++ b/Endless/WebViewTab.m @@ -50,7 +50,7 @@ - (id)initWithFrame:(CGRect)frame withRestorationIdentifier:(NSString *)rid /* re-register user agent with our hash, which should only affect this UIWebView */ [[NSUserDefaults standardUserDefaults] registerDefaults:@{ @"UserAgent": [NSString stringWithFormat:@"%@/%lu", [appDelegate defaultUserAgent], (unsigned long)self.hash] }]; - _webView = [[UIWebView alloc] initWithFrame:CGRectZero]; + SILENCE_DEPRECATION(_webView = [[UIWebView alloc] initWithFrame:CGRectZero]); _needsRefresh = FALSE; if (rid != nil) { [_webView setRestorationIdentifier:rid]; @@ -324,8 +324,11 @@ - (void)searchFor:(NSString *)query } /* this will only fire for top-level requests (and iframes), not page elements */ +SILENCE_DEPRECATION_ON - (BOOL)webView:(UIWebView *)__webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { +SILENCE_DEPRECATION_OFF + NSURL *url = [request URL]; /* treat endlesshttps?:// links clicked inside of web pages as normal links */ @@ -475,8 +478,11 @@ - (BOOL)webView:(UIWebView *)__webView shouldStartLoadWithRequest:(NSURLRequest return NO; } +SILENCE_DEPRECATION_ON - (void)webViewDidStartLoad:(UIWebView *)__webView { +SILENCE_DEPRECATION_OFF + /* reset and then let WebViewController animate to our actual progress */ [self setProgress:@0.0]; [self setProgress:@0.1]; @@ -485,8 +491,10 @@ - (void)webViewDidStartLoad:(UIWebView *)__webView self.url = [[__webView request] URL]; } +SILENCE_DEPRECATION_ON - (void)webViewDidFinishLoad:(UIWebView *)__webView { +SILENCE_DEPRECATION_OFF #ifdef TRACE NSLog(@"[Tab %@] finished loading page/iframe %@, security level is %lu", self.tabIndex, [[[__webView request] URL] absoluteString], self.secureMode); #endif @@ -522,8 +530,11 @@ - (void)webViewDidFinishLoad:(UIWebView *)__webView skipHistory = NO; } +SILENCE_DEPRECATION_ON - (void)webView:(UIWebView *)__webView didFailLoadWithError:(NSError *)error { +SILENCE_DEPRECATION_OFF + BOOL isTLSError = false; self.url = __webView.request.URL; @@ -570,7 +581,9 @@ - (void)webView:(UIWebView *)__webView didFailLoadWithError:(NSError *)error #ifdef TRACE NSLog(@"[Tab %@] not showing dialog for non-origin error: %@ (%@)", self.tabIndex, msg, error); #endif +SILENCE_DEPRECATION_ON [self webViewDidFinishLoad:__webView]; +SILENCE_DEPRECATION_OFF return; } } @@ -613,12 +626,17 @@ - (void)webView:(UIWebView *)__webView didFailLoadWithError:(NSError *)error } [[appDelegate webViewController] presentViewController:uiac animated:YES completion:nil]; - + +SILENCE_DEPRECATION_ON [self webViewDidFinishLoad:__webView]; +SILENCE_DEPRECATION_OFF } +SILENCE_DEPRECATION_ON - (void)webView:(UIWebView *)__webView callbackWith:(NSString *)callback { +SILENCE_DEPRECATION_OFF + NSString *finalcb = [NSString stringWithFormat:@"(function() { %@; __endless.ipcDone = (new Date()).getTime(); })();", callback]; #ifdef TRACE_IPC diff --git a/External/CKHTTPConnection.m b/External/CKHTTPConnection.m index 099b7cc..f6b20eb 100644 --- a/External/CKHTTPConnection.m +++ b/External/CKHTTPConnection.m @@ -16,6 +16,7 @@ #import "CKHTTPConnection.h" #import "HostSettings.h" #import "SSLCertificate.h" +#import "../Endless/SilenceDeprecation.h" @interface CKHTTPConnection () - (CFHTTPMessageRef)HTTPRequest; @@ -91,7 +92,8 @@ - (void)start { NSAssert(!_HTTPStream, @"Connection already started"); HostSettings *hs; - + +SILENCE_DEPRECATION_ON if (_HTTPBodyStream) _HTTPStream = (__bridge_transfer NSInputStream *)(CFReadStreamCreateForStreamedHTTPRequest(NULL, [self HTTPRequest], (__bridge CFReadStreamRef)_HTTPBodyStream)); else @@ -105,7 +107,9 @@ - (void)start CFReadStreamSetProperty((__bridge CFReadStreamRef)(_HTTPStream), kCFStreamPropertyHTTPAttemptPersistentConnection, kCFBooleanTrue); else CFReadStreamSetProperty((__bridge CFReadStreamRef)(_HTTPStream), kCFStreamPropertyHTTPAttemptPersistentConnection, kCFBooleanFalse); - + +SILENCE_DEPRECATION_OFF + /* set SSL protocol version enforcement before opening, when using kCFStreamSSLLevel */ NSURL *url = (__bridge_transfer NSURL *)(CFHTTPMessageCopyRequestURL([self HTTPRequest])); if ([[[url scheme] lowercaseString] isEqualToString:@"https"]) { @@ -253,7 +257,8 @@ - (void)cancel - (void)stream:(NSInputStream *)theStream handleEvent:(NSStreamEvent)streamEvent { NSParameterAssert(theStream == [self stream]); - + +SILENCE_DEPRECATION_ON NSURL *URL = [theStream propertyForKey:(NSString *)kCFStreamPropertyHTTPFinalURL]; if (!_haveReceivedResponse) { @@ -262,7 +267,8 @@ - (void)stream:(NSInputStream *)theStream handleEvent:(NSStreamEvent)streamEvent NSHTTPURLResponse *URLResponse = [[NSHTTPURLResponse alloc] initWithURL:URL statusCode:CFHTTPMessageGetResponseStatusCode(response) HTTPVersion:(__bridge NSString * _Nullable)(CFHTTPMessageCopyVersion(response)) headerFields:(__bridge NSDictionary * _Nullable)(CFHTTPMessageCopyAllHeaderFields(response))]; NSData *d = (__bridge NSData *)CFHTTPMessageCopySerializedMessage((__bridge CFHTTPMessageRef _Nonnull)([_HTTPStream propertyForKey:(NSString *)kCFStreamPropertyHTTPResponseHeader])); - +SILENCE_DEPRECATION_OFF + /* work around bug where CFHTTPMessageIsHeaderComplete reports true but there is no actual header data to be found */ if ([d length] < 5) { #ifdef TRACE @@ -452,8 +458,6 @@ - (id)initWithResponse:(CFHTTPMessageRef)response { NSParameterAssert(response); -#warning "Instance variable used while 'self' is not set to the result of [self init]" - // Try to create an authentication object from the response _HTTPAuthentication = CFHTTPAuthenticationCreateFromResponse(NULL, response); if (![self CFHTTPAuthentication]) diff --git a/External/OnePasswordExtension.m b/External/OnePasswordExtension.m index 7b7b663..24f335e 100644 --- a/External/OnePasswordExtension.m +++ b/External/OnePasswordExtension.m @@ -6,6 +6,7 @@ // #import "OnePasswordExtension.h" +#import "../Endless/SilenceDeprecation.h" // Version #define VERSION_NUMBER @(184) @@ -208,10 +209,13 @@ - (void)changePasswordForLoginForURLString:(nonnull NSString *)URLString loginDe - (void)fillItemIntoWebView:(nonnull id)webView forViewController:(nonnull UIViewController *)viewController sender:(nullable id)sender showOnlyLogins:(BOOL)yesOrNo completion:(nonnull OnePasswordSuccessCompletionBlock)completion { NSAssert(webView != nil, @"webView must not be nil"); NSAssert(viewController != nil, @"viewController must not be nil"); - NSAssert([webView isKindOfClass:[UIWebView class]] || [webView isKindOfClass:[WKWebView class]], @"webView must be an instance of WKWebView or UIWebView."); + SILENCE_DEPRECATION(NSAssert([webView isKindOfClass:[UIWebView class]] || [webView isKindOfClass:[WKWebView class]], @"webView must be an instance of WKWebView or UIWebView.")); #ifdef __IPHONE_8_0 +SILENCE_DEPRECATION_ON if ([webView isKindOfClass:[UIWebView class]]) { +SILENCE_DEPRECATION_OFF + [self fillItemIntoUIWebView:webView webViewController:viewController sender:(id)sender showOnlyLogins:yesOrNo completion:^(BOOL success, NSError *error) { if (completion) { completion(success, error); @@ -238,11 +242,15 @@ - (BOOL)isOnePasswordExtensionActivityType:(nullable NSString *)activityType { - (void)createExtensionItemForWebView:(nonnull id)webView completion:(nonnull OnePasswordExtensionItemCompletionBlock)completion { NSAssert(webView != nil, @"webView must not be nil"); - NSAssert([webView isKindOfClass:[UIWebView class]] || [webView isKindOfClass:[WKWebView class]], @"webView must be an instance of WKWebView or UIWebView."); + SILENCE_DEPRECATION(NSAssert([webView isKindOfClass:[UIWebView class]] || [webView isKindOfClass:[WKWebView class]], @"webView must be an instance of WKWebView or UIWebView.")); #ifdef __IPHONE_8_0 + +SILENCE_DEPRECATION_ON if ([webView isKindOfClass:[UIWebView class]]) { UIWebView *uiWebView = (UIWebView *)webView; +SILENCE_DEPRECATION_OFF + NSString *collectedPageDetails = [uiWebView stringByEvaluatingJavaScriptFromString:OPWebViewCollectFieldsScript]; [self createExtensionItemForURLString:uiWebView.request.URL.absoluteString webPageDetails:collectedPageDetails completion:completion]; @@ -401,7 +409,10 @@ - (void)fillItemIntoWKWebView:(nonnull WKWebView *)webView forViewController:(no } #endif +SILENCE_DEPRECATION_ON - (void)fillItemIntoUIWebView:(nonnull UIWebView *)webView webViewController:(nonnull UIViewController *)viewController sender:(nullable id)sender showOnlyLogins:(BOOL)yesOrNo completion:(nonnull OnePasswordSuccessCompletionBlock)completion { +SILENCE_DEPRECATION_OFF + NSString *collectedPageDetails = [webView stringByEvaluatingJavaScriptFromString:OPWebViewCollectFieldsScript]; [self findLoginIn1PasswordWithURLString:webView.request.URL.absoluteString collectedPageDetails:collectedPageDetails forWebViewController:viewController sender:sender withWebView:webView showOnlyLogins:yesOrNo completion:^(BOOL success, NSError *error) { if (completion) { @@ -425,8 +436,11 @@ - (void)executeFillScript:(NSString * __nullable)fillScript inWebView:(nonnull i [scriptSource appendFormat:@"(document, %@, undefined);", fillScript]; #ifdef __IPHONE_8_0 +SILENCE_DEPRECATION_ON if ([webView isKindOfClass:[UIWebView class]]) { NSString *result = [((UIWebView *)webView) stringByEvaluatingJavaScriptFromString:scriptSource]; +SILENCE_DEPRECATION_OFF + BOOL success = (result != nil); NSError *error = nil; From 2465e72e9ef4f92bc42510e9d5b12f9a7033c32a Mon Sep 17 00:00:00 2001 From: Benjamin Erhart Date: Fri, 22 Mar 2019 16:48:50 +0100 Subject: [PATCH 06/18] Fixed retain cycle warnings. --- Endless/WebViewController.m | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Endless/WebViewController.m b/Endless/WebViewController.m index 941895f..e410b08 100644 --- a/Endless/WebViewController.m +++ b/Endless/WebViewController.m @@ -615,8 +615,10 @@ - (WebViewTab *)addNewTabForURL:(NSURL *)url forRestoration:(BOOL)restoration wi - (void)addNewTabFromToolbar:(id)_id { + UITextField *urlField = self->urlField; + [self addNewTabForURL:nil forRestoration:NO withAnimation:WebViewTabAnimationDefault withCompletionBlock:^(BOOL finished) { - [self->urlField becomeFirstResponder]; + [urlField becomeFirstResponder]; }]; } @@ -714,8 +716,11 @@ - (void)removeTab:(NSNumber *)tabNumber andFocusTab:(NSNumber *)toFocus else { /* no tabs left, add one and zoom out */ [self reindexTabs]; + + UITextField *urlField = self->urlField; + [self addNewTabForURL:nil forRestoration:false withAnimation:WebViewTabAnimationDefault withCompletionBlock:^(BOOL finished) { - [self->urlField becomeFirstResponder]; + [urlField becomeFirstResponder]; }]; return; } From 40b1e652b14d893f7a86a220c5eec4755db00a9d Mon Sep 17 00:00:00 2001 From: Benjamin Erhart Date: Fri, 22 Mar 2019 17:08:24 +0100 Subject: [PATCH 07/18] Silence warning about leak when calling #performSelector, since the calls themselves are actually ok. --- Endless.xcodeproj/project.pbxproj | 4 +-- Endless/HostSettingsController.m | 4 +-- ...SilenceDeprecation.h => SilenceWarnings.h} | 26 ++++++++++++++----- Endless/WebViewController.m | 2 +- Endless/WebViewMenuController.m | 3 ++- Endless/WebViewTab.h | 4 +-- Endless/WebViewTab.m | 14 +++++----- External/CKHTTPConnection.m | 6 ++--- External/OnePasswordExtension.m | 10 +++---- 9 files changed, 43 insertions(+), 30 deletions(-) rename Endless/{SilenceDeprecation.h => SilenceWarnings.h} (54%) diff --git a/Endless.xcodeproj/project.pbxproj b/Endless.xcodeproj/project.pbxproj index 4c47c80..01ae345 100644 --- a/Endless.xcodeproj/project.pbxproj +++ b/Endless.xcodeproj/project.pbxproj @@ -241,7 +241,7 @@ A024D5AD1ECEF10F00B28CC5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Endless/Base.lproj/OnePasswordExtension.strings; sourceTree = ""; }; A024D5B01ECEF11A00B28CC5 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = Endless/de.lproj/Localizable.strings; sourceTree = ""; }; A024D5B11ECEF11A00B28CC5 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = Endless/de.lproj/OnePasswordExtension.strings; sourceTree = ""; }; - A07E147222381A8700B76F77 /* SilenceDeprecation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SilenceDeprecation.h; sourceTree = ""; }; + A07E147222381A8700B76F77 /* SilenceWarnings.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SilenceWarnings.h; sourceTree = ""; }; FC10255E5E506A0C25D6276B /* libPods-Endless Tests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Endless Tests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; FDEC322B35C8D861612E24E3 /* Pods-Endless Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Endless Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Endless Tests/Pods-Endless Tests.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -373,7 +373,7 @@ 013E71CF1E5150C000BB0572 /* urlblocker.json */, 015748031E208C5000DB2044 /* UIResponder+FirstResponder.h */, 015748041E208C5000DB2044 /* UIResponder+FirstResponder.m */, - A07E147222381A8700B76F77 /* SilenceDeprecation.h */, + A07E147222381A8700B76F77 /* SilenceWarnings.h */, ); name = "Supporting Files"; path = Endless; diff --git a/Endless/HostSettingsController.m b/Endless/HostSettingsController.m index 2392312..6d49f6c 100644 --- a/Endless/HostSettingsController.m +++ b/Endless/HostSettingsController.m @@ -9,11 +9,11 @@ #import "HostSettings.h" #import "HostSettingsController.h" -#import "SilenceDeprecation.h" +#import "SilenceWarnings.h" SILENCE_DEPRECATION_ON #import "XLForm.h" -SILENCE_DEPRECATION_OFF +SILENCE_WARNINGS_OFF @interface HostSettingsXLFormViewController : XLFormViewController @property (copy, nonatomic) void (^disappearCallback)(HostSettingsXLFormViewController *); diff --git a/Endless/SilenceDeprecation.h b/Endless/SilenceWarnings.h similarity index 54% rename from Endless/SilenceDeprecation.h rename to Endless/SilenceWarnings.h index 62f1ae0..bfd10b0 100644 --- a/Endless/SilenceDeprecation.h +++ b/Endless/SilenceWarnings.h @@ -1,22 +1,19 @@ // -// SilenceDeprecation.h +// SilenceWarnings.h // Endless // // Created by Benjamin Erhart on 12.03.19. // Copyright © 2019 jcs. All rights reserved. // -#ifndef SilenceDeprecation_h -#define SilenceDeprecation_h +#ifndef SilenceWarnings_h +#define SilenceWarnings_h #define SILENCE_DEPRECATION_ON \ _Pragma("clang diagnostic push") \ _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") \ _Pragma("clang diagnostic ignored \"-Wdeprecated-implementations\"") -#define SILENCE_DEPRECATION_OFF \ -_Pragma("clang diagnostic pop") - #define SILENCE_DEPRECATION(expr) \ do { \ _Pragma("clang diagnostic push") \ @@ -26,4 +23,19 @@ expr; \ _Pragma("clang diagnostic pop") \ } while(0) -#endif /* SilenceDeprecation_h */ +#define SILENCE_PERFORM_SELECTOR_LEAKS_ON \ +_Pragma("clang diagnostic push") \ +_Pragma("clang diagnostic ignored \"-Warc-performSelector-leaks\"") + +#define SILENCE_PERFORM_SELECTOR_LEAKS(expr) \ +do { \ +_Pragma("clang diagnostic push") \ +_Pragma("clang diagnostic ignored \"-Warc-performSelector-leaks\"") \ +expr; \ +_Pragma("clang diagnostic pop") \ +} while(0) + +#define SILENCE_WARNINGS_OFF \ +_Pragma("clang diagnostic pop") + +#endif /* SilenceWarnings_h */ diff --git a/Endless/WebViewController.m b/Endless/WebViewController.m index e410b08..91de45a 100644 --- a/Endless/WebViewController.m +++ b/Endless/WebViewController.m @@ -1225,7 +1225,7 @@ - (NSString *)buildDefaultUserAgent SILENCE_DEPRECATION_ON UIWebView *twv = [[UIWebView alloc] initWithFrame:CGRectZero]; - SILENCE_DEPRECATION_OFF + SILENCE_WARNINGS_OFF NSString *ua = [twv stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"]; NSMutableArray *uapieces = [[NSMutableArray alloc] initWithArray:[ua componentsSeparatedByString:@" "]]; diff --git a/Endless/WebViewMenuController.m b/Endless/WebViewMenuController.m index da8ad78..f6b12fb 100644 --- a/Endless/WebViewMenuController.m +++ b/Endless/WebViewMenuController.m @@ -175,7 +175,8 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath SEL action = NSSelectorFromString([button objectForKey:FUNC]); if ([self respondsToSelector:action]) - [self performSelector:action]; + // The calls are hardcoded, there will be no leakage. + SILENCE_PERFORM_SELECTOR_LEAKS([self performSelector:action]); else NSLog(@"can't call %@", NSStringFromSelector(action)); } diff --git a/Endless/WebViewTab.h b/Endless/WebViewTab.h index 2e2a117..8b262f9 100644 --- a/Endless/WebViewTab.h +++ b/Endless/WebViewTab.h @@ -9,7 +9,7 @@ #import #import "SSLCertificate.h" -#import "SilenceDeprecation.h" +#import "SilenceWarnings.h" #define ZOOM_OUT_SCALE 0.8 #define ZOOM_OUT_SCALE_ROTATED 0.7 @@ -102,7 +102,7 @@ static const struct keyboard_map_entry { @property (strong, atomic) UIView *viewHolder; SILENCE_DEPRECATION_ON @property (strong, atomic) UIWebView *webView; -SILENCE_DEPRECATION_OFF +SILENCE_WARNINGS_OFF @property (strong, atomic) UIRefreshControl *refresher; @property (strong, atomic) NSURL *url; @property BOOL needsRefresh; diff --git a/Endless/WebViewTab.m b/Endless/WebViewTab.m index 41c2c42..f3a77a0 100644 --- a/Endless/WebViewTab.m +++ b/Endless/WebViewTab.m @@ -327,7 +327,7 @@ - (void)searchFor:(NSString *)query SILENCE_DEPRECATION_ON - (BOOL)webView:(UIWebView *)__webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { -SILENCE_DEPRECATION_OFF +SILENCE_WARNINGS_OFF NSURL *url = [request URL]; @@ -481,7 +481,7 @@ - (BOOL)webView:(UIWebView *)__webView shouldStartLoadWithRequest:(NSURLRequest SILENCE_DEPRECATION_ON - (void)webViewDidStartLoad:(UIWebView *)__webView { -SILENCE_DEPRECATION_OFF +SILENCE_WARNINGS_OFF /* reset and then let WebViewController animate to our actual progress */ [self setProgress:@0.0]; @@ -494,7 +494,7 @@ - (void)webViewDidStartLoad:(UIWebView *)__webView SILENCE_DEPRECATION_ON - (void)webViewDidFinishLoad:(UIWebView *)__webView { -SILENCE_DEPRECATION_OFF +SILENCE_WARNINGS_OFF #ifdef TRACE NSLog(@"[Tab %@] finished loading page/iframe %@, security level is %lu", self.tabIndex, [[[__webView request] URL] absoluteString], self.secureMode); #endif @@ -533,7 +533,7 @@ - (void)webViewDidFinishLoad:(UIWebView *)__webView SILENCE_DEPRECATION_ON - (void)webView:(UIWebView *)__webView didFailLoadWithError:(NSError *)error { -SILENCE_DEPRECATION_OFF +SILENCE_WARNINGS_OFF BOOL isTLSError = false; @@ -583,7 +583,7 @@ - (void)webView:(UIWebView *)__webView didFailLoadWithError:(NSError *)error #endif SILENCE_DEPRECATION_ON [self webViewDidFinishLoad:__webView]; -SILENCE_DEPRECATION_OFF +SILENCE_WARNINGS_OFF return; } } @@ -629,13 +629,13 @@ - (void)webView:(UIWebView *)__webView didFailLoadWithError:(NSError *)error SILENCE_DEPRECATION_ON [self webViewDidFinishLoad:__webView]; -SILENCE_DEPRECATION_OFF +SILENCE_WARNINGS_OFF } SILENCE_DEPRECATION_ON - (void)webView:(UIWebView *)__webView callbackWith:(NSString *)callback { -SILENCE_DEPRECATION_OFF +SILENCE_WARNINGS_OFF NSString *finalcb = [NSString stringWithFormat:@"(function() { %@; __endless.ipcDone = (new Date()).getTime(); })();", callback]; diff --git a/External/CKHTTPConnection.m b/External/CKHTTPConnection.m index f6b20eb..a19674d 100644 --- a/External/CKHTTPConnection.m +++ b/External/CKHTTPConnection.m @@ -16,7 +16,7 @@ #import "CKHTTPConnection.h" #import "HostSettings.h" #import "SSLCertificate.h" -#import "../Endless/SilenceDeprecation.h" +#import "../Endless/SilenceWarnings.h" @interface CKHTTPConnection () - (CFHTTPMessageRef)HTTPRequest; @@ -108,7 +108,7 @@ - (void)start else CFReadStreamSetProperty((__bridge CFReadStreamRef)(_HTTPStream), kCFStreamPropertyHTTPAttemptPersistentConnection, kCFBooleanFalse); -SILENCE_DEPRECATION_OFF +SILENCE_WARNINGS_OFF /* set SSL protocol version enforcement before opening, when using kCFStreamSSLLevel */ NSURL *url = (__bridge_transfer NSURL *)(CFHTTPMessageCopyRequestURL([self HTTPRequest])); @@ -267,7 +267,7 @@ - (void)stream:(NSInputStream *)theStream handleEvent:(NSStreamEvent)streamEvent NSHTTPURLResponse *URLResponse = [[NSHTTPURLResponse alloc] initWithURL:URL statusCode:CFHTTPMessageGetResponseStatusCode(response) HTTPVersion:(__bridge NSString * _Nullable)(CFHTTPMessageCopyVersion(response)) headerFields:(__bridge NSDictionary * _Nullable)(CFHTTPMessageCopyAllHeaderFields(response))]; NSData *d = (__bridge NSData *)CFHTTPMessageCopySerializedMessage((__bridge CFHTTPMessageRef _Nonnull)([_HTTPStream propertyForKey:(NSString *)kCFStreamPropertyHTTPResponseHeader])); -SILENCE_DEPRECATION_OFF +SILENCE_WARNINGS_OFF /* work around bug where CFHTTPMessageIsHeaderComplete reports true but there is no actual header data to be found */ if ([d length] < 5) { diff --git a/External/OnePasswordExtension.m b/External/OnePasswordExtension.m index 24f335e..cb55b66 100644 --- a/External/OnePasswordExtension.m +++ b/External/OnePasswordExtension.m @@ -6,7 +6,7 @@ // #import "OnePasswordExtension.h" -#import "../Endless/SilenceDeprecation.h" +#import "../Endless/SilenceWarnings.h" // Version #define VERSION_NUMBER @(184) @@ -214,7 +214,7 @@ - (void)fillItemIntoWebView:(nonnull id)webView forViewController:(nonnull UIVie #ifdef __IPHONE_8_0 SILENCE_DEPRECATION_ON if ([webView isKindOfClass:[UIWebView class]]) { -SILENCE_DEPRECATION_OFF +SILENCE_WARNINGS_OFF [self fillItemIntoUIWebView:webView webViewController:viewController sender:(id)sender showOnlyLogins:yesOrNo completion:^(BOOL success, NSError *error) { if (completion) { @@ -249,7 +249,7 @@ - (void)createExtensionItemForWebView:(nonnull id)webView completion:(nonnull On SILENCE_DEPRECATION_ON if ([webView isKindOfClass:[UIWebView class]]) { UIWebView *uiWebView = (UIWebView *)webView; -SILENCE_DEPRECATION_OFF +SILENCE_WARNINGS_OFF NSString *collectedPageDetails = [uiWebView stringByEvaluatingJavaScriptFromString:OPWebViewCollectFieldsScript]; @@ -411,7 +411,7 @@ - (void)fillItemIntoWKWebView:(nonnull WKWebView *)webView forViewController:(no SILENCE_DEPRECATION_ON - (void)fillItemIntoUIWebView:(nonnull UIWebView *)webView webViewController:(nonnull UIViewController *)viewController sender:(nullable id)sender showOnlyLogins:(BOOL)yesOrNo completion:(nonnull OnePasswordSuccessCompletionBlock)completion { -SILENCE_DEPRECATION_OFF +SILENCE_WARNINGS_OFF NSString *collectedPageDetails = [webView stringByEvaluatingJavaScriptFromString:OPWebViewCollectFieldsScript]; [self findLoginIn1PasswordWithURLString:webView.request.URL.absoluteString collectedPageDetails:collectedPageDetails forWebViewController:viewController sender:sender withWebView:webView showOnlyLogins:yesOrNo completion:^(BOOL success, NSError *error) { @@ -439,7 +439,7 @@ - (void)executeFillScript:(NSString * __nullable)fillScript inWebView:(nonnull i SILENCE_DEPRECATION_ON if ([webView isKindOfClass:[UIWebView class]]) { NSString *result = [((UIWebView *)webView) stringByEvaluatingJavaScriptFromString:scriptSource]; -SILENCE_DEPRECATION_OFF +SILENCE_WARNINGS_OFF BOOL success = (result != nil); NSError *error = nil; From 7da71cccd8f12c98dff891c726b0cda02a49ccbb Mon Sep 17 00:00:00 2001 From: Benjamin Erhart Date: Fri, 22 Mar 2019 17:21:38 +0100 Subject: [PATCH 08/18] Removed deprecated method #application:openURL:sourceAplication:annotation, which is deprecated since iOS 9 and where its successor is already implemented. --- Endless/AppDelegate.m | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/Endless/AppDelegate.m b/Endless/AppDelegate.m index fc06926..5dac4c8 100644 --- a/Endless/AppDelegate.m +++ b/Endless/AppDelegate.m @@ -111,22 +111,6 @@ - (void)applicationWillTerminate:(UIApplication *)application [application ignoreSnapshotOnNextApplicationLaunch]; } -- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation -{ -#ifdef TRACE - NSLog(@"[AppDelegate] request to open url at launch: %@", url); -#endif - if ([[[url scheme] lowercaseString] isEqualToString:@"endlesshttp"]) - url = [NSURL URLWithString:[[url absoluteString] stringByReplacingCharactersInRange:NSMakeRange(0, [@"endlesshttp" length]) withString:@"http"]]; - else if ([[[url scheme] lowercaseString] isEqualToString:@"endlesshttps"]) - url = [NSURL URLWithString:[[url absoluteString] stringByReplacingCharactersInRange:NSMakeRange(0, [@"endlesshttps" length]) withString:@"https"]]; - - /* delay until we're done drawing the UI */ - self.urlToOpenAtLaunch = url; - - return YES; -} - - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options { #ifdef TRACE From 8f998f8d3d5a6e0f23eae426b5b019fa02e4bf1a Mon Sep 17 00:00:00 2001 From: Benjamin Erhart Date: Fri, 22 Mar 2019 17:24:00 +0100 Subject: [PATCH 09/18] Update to CocoaPods 1.6.1. --- Podfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Podfile.lock b/Podfile.lock index 2d3ef77..62e0b2c 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -104,4 +104,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 26382b338af288c4202e8abd44a2f9ff01e82209 -COCOAPODS: 1.6.0 +COCOAPODS: 1.6.1 From 440f66fd16d2c7e17a21972ca24d128a11a6b769 Mon Sep 17 00:00:00 2001 From: Benjamin Erhart Date: Fri, 22 Mar 2019 18:04:44 +0100 Subject: [PATCH 10/18] Fixed issue on iPhone X, where the address field moves under the notch when the "Report a bug" item is tapped in settings. --- Endless/AppDelegate.m | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/Endless/AppDelegate.m b/Endless/AppDelegate.m index 5dac4c8..226e628 100644 --- a/Endless/AppDelegate.m +++ b/Endless/AppDelegate.m @@ -122,9 +122,22 @@ - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDiction else if ([[[url scheme] lowercaseString] isEqualToString:@"endlesshttps"]) url = [NSURL URLWithString:[[url absoluteString] stringByReplacingCharactersInRange:NSMakeRange(0, [@"endlesshttps" length]) withString:@"https"]]; - [[self webViewController] dismissViewControllerAnimated:YES completion:nil]; - [[self webViewController] addNewTabForURL:url]; - + // In case, a modal view controller is overlaying the WebViewController, + // we need to close it *before* adding a new tab. Otherwise, the UI will + // be broken on iPhone-X-type devices: The address field will be in the + // notch area. + if ([self webViewController].presentedViewController != nil) + { + [[self webViewController] dismissViewControllerAnimated:YES completion:^{ + [[self webViewController] addNewTabForURL:url]; + }]; + } + // If there's no modal view controller, however, the completion block would + // never be called. + else { + [[self webViewController] addNewTabForURL:url]; + } + return YES; } From fa8f89c00875dee34d981a11875045e659ccc284 Mon Sep 17 00:00:00 2001 From: Benjamin Erhart Date: Tue, 2 Apr 2019 17:52:24 +0200 Subject: [PATCH 11/18] Fixed issues presented by new Xcode 10.2. --- Endless.xcodeproj/project.pbxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Endless.xcodeproj/project.pbxproj b/Endless.xcodeproj/project.pbxproj index 01ae345..61c48ea 100644 --- a/Endless.xcodeproj/project.pbxproj +++ b/Endless.xcodeproj/project.pbxproj @@ -604,7 +604,7 @@ }; buildConfigurationList = 01801E8D1A32CA2A002B4718 /* Build configuration list for PBXProject "Endless" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, From e3a0bb8dabaab2094210bcc16754cf8e4436d3f5 Mon Sep 17 00:00:00 2001 From: Benjamin Erhart Date: Tue, 2 Apr 2019 17:53:28 +0200 Subject: [PATCH 12/18] Removed check for orientation when calculating status bar height. Looks like a bugfix for an older iOS version, but now actually breaks things on iOS 11/12 on iPad landscape. --- Endless/WebViewController.m | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Endless/WebViewController.m b/Endless/WebViewController.m index 91de45a..55763e7 100644 --- a/Endless/WebViewController.m +++ b/Endless/WebViewController.m @@ -372,8 +372,7 @@ - (void)viewSafeAreaInsetsDidChange - (void)viewDidLayoutSubviews { - UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; - float statusBarHeight = (UIInterfaceOrientationIsLandscape(orientation) ? 0 : [[UIApplication sharedApplication] statusBarFrame].size.height); + float statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height; /* views are transforming and we may calculate things incorrectly here, so just ignore this request */ if (showingTabs) From ba947f57070ef27b9df1e5aa35165046435ce435 Mon Sep 17 00:00:00 2001 From: Benjamin Erhart Date: Wed, 3 Apr 2019 10:18:15 +0200 Subject: [PATCH 13/18] Allow static image files when using "strict" content mode. --- Endless/URLInterceptor.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Endless/URLInterceptor.m b/Endless/URLInterceptor.m index b53dd35..86dcb25 100644 --- a/Endless/URLInterceptor.m +++ b/Endless/URLInterceptor.m @@ -461,7 +461,7 @@ - (void)HTTPConnection:(CKHTTPConnection *)connection didReceiveResponse:(NSHTTP NSString *CSPmode = [self.originHostSettings settingOrDefault:HOST_SETTINGS_KEY_CSP]; if ([CSPmode isEqualToString:HOST_SETTINGS_CSP_STRICT]) - CSPheader = @"connect-src 'none'; default-src 'none'; font-src 'none'; media-src 'none'; object-src 'none'; sandbox allow-forms allow-top-navigation; script-src 'none'; style-src 'unsafe-inline' *; report-uri;"; + CSPheader = @"connect-src 'none'; default-src 'none'; font-src 'none'; media-src 'none'; object-src 'none'; sandbox allow-forms allow-top-navigation; script-src 'none'; style-src 'unsafe-inline' *; image-src 'unsafe-inline' *; report-uri;"; else if ([CSPmode isEqualToString:HOST_SETTINGS_CSP_BLOCK_CONNECT]) CSPheader = @"connect-src 'none'; media-src 'none'; object-src 'none'; report-uri;"; From 9f64ab4a451ea7821038ed97763a65f2349741f6 Mon Sep 17 00:00:00 2001 From: Benjamin Erhart Date: Wed, 3 Apr 2019 10:46:54 +0200 Subject: [PATCH 14/18] Added "Open in Background Tab" feature into long-tap context menu for links. --- Endless/Base.lproj/Localizable.strings | Bin 20228 -> 20414 bytes Endless/WebViewTab.m | 6 ++++++ Endless/de.lproj/Localizable.strings | Bin 20766 -> 20950 bytes 3 files changed, 6 insertions(+) diff --git a/Endless/Base.lproj/Localizable.strings b/Endless/Base.lproj/Localizable.strings index 9878d87ce0ad23c994553cd321025d5a2964124e..e7d16614455404be5ab546bdf485abca4e2a91b0 100644 GIT binary patch delta 69 zcmZpf$GC4kXn5DF6U6$OaYw diff --git a/Endless/WebViewTab.m b/Endless/WebViewTab.m index f3a77a0..7026b7c 100644 --- a/Endless/WebViewTab.m +++ b/Endless/WebViewTab.m @@ -778,6 +778,11 @@ - (void)pressedMenu:(UIGestureRecognizer *)event newtab.openedByTabHash = [NSNumber numberWithLong:self.hash]; }]; + UIAlertAction *openBackgroundTabAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Open in Background Tab", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { + WebViewTab *newtab = [[self->appDelegate webViewController] addNewTabForURL:[NSURL URLWithString:href] forRestoration:NO withAnimation:WebViewTabAnimationHidden withCompletionBlock:nil]; + newtab.openedByTabHash = [NSNumber numberWithLong:self.hash]; + }]; + UIAlertAction *openSafariAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Open in Safari", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { [[UIApplication sharedApplication] openURL:[NSURL URLWithString:href] options:@{} completionHandler:nil]; }]; @@ -804,6 +809,7 @@ - (void)pressedMenu:(UIGestureRecognizer *)event if (href) { [alertController addAction:openAction]; [alertController addAction:openNewTabAction]; + [alertController addAction:openBackgroundTabAction]; [alertController addAction:openSafariAction]; } diff --git a/Endless/de.lproj/Localizable.strings b/Endless/de.lproj/Localizable.strings index 28e13aeb7f893f896abab5129f6e7910c4d0dfda..cecf0de07806a2eebf428bc176b7708b6aee33ba 100644 GIT binary patch delta 94 zcmbQYi1FHD#tl9C-cAgO49N`H4CxF-4EYSD40#MG3 Date: Wed, 3 Apr 2019 11:59:49 +0200 Subject: [PATCH 15/18] Fixed broken "Save Image" functionality. --- Endless.xcodeproj/project.pbxproj | 14 ++++++++++++++ Endless/Info.plist | 2 ++ Endless/de.lproj/InfoPlist.strings | 8 ++++++++ Endless/en.lproj/InfoPlist.strings | 8 ++++++++ 4 files changed, 32 insertions(+) create mode 100644 Endless/de.lproj/InfoPlist.strings create mode 100644 Endless/en.lproj/InfoPlist.strings diff --git a/Endless.xcodeproj/project.pbxproj b/Endless.xcodeproj/project.pbxproj index 61c48ea..36d1ea4 100644 --- a/Endless.xcodeproj/project.pbxproj +++ b/Endless.xcodeproj/project.pbxproj @@ -80,6 +80,7 @@ 01FE82961FC0DC94006E5777 /* BlackIcon-83.5@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 01FE82951FC0DC94006E5777 /* BlackIcon-83.5@2x.png */; }; A024D5AE1ECEF10F00B28CC5 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = A024D5AA1ECEF10F00B28CC5 /* Localizable.strings */; }; A024D5AF1ECEF10F00B28CC5 /* OnePasswordExtension.strings in Resources */ = {isa = PBXBuildFile; fileRef = A024D5AC1ECEF10F00B28CC5 /* OnePasswordExtension.strings */; }; + A09A2AA52254BB2E00A3EEF0 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = A09A2AA72254BB2E00A3EEF0 /* InfoPlist.strings */; }; AA9A5FECA2E668F834FDECD9 /* libPods-Endless.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 095BC7BD685DE17FADDBF166 /* libPods-Endless.a */; }; D919EA71FF999D55CCC96334 /* libPods-Endless Tests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FC10255E5E506A0C25D6276B /* libPods-Endless Tests.a */; }; /* End PBXBuildFile section */ @@ -242,6 +243,8 @@ A024D5B01ECEF11A00B28CC5 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = Endless/de.lproj/Localizable.strings; sourceTree = ""; }; A024D5B11ECEF11A00B28CC5 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = Endless/de.lproj/OnePasswordExtension.strings; sourceTree = ""; }; A07E147222381A8700B76F77 /* SilenceWarnings.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SilenceWarnings.h; sourceTree = ""; }; + A09A2AA62254BB2E00A3EEF0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + A09A2AA82254BB2F00A3EEF0 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/InfoPlist.strings; sourceTree = ""; }; FC10255E5E506A0C25D6276B /* libPods-Endless Tests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Endless Tests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; FDEC322B35C8D861612E24E3 /* Pods-Endless Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Endless Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Endless Tests/Pods-Endless Tests.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -361,6 +364,7 @@ 01D42C3B1E0A37DB00566022 /* Endless.entitlements */, 018333CF1A351B3B00670CD1 /* Endless-Prefix.pch */, 01801E961A32CA2A002B4718 /* Info.plist */, + A09A2AA72254BB2E00A3EEF0 /* InfoPlist.strings */, 01801E971A32CA2A002B4718 /* main.m */, 01F7CB4C1A52FC4E00F42B73 /* NSString+IPAddress.h */, 01F7CB4D1A52FC4E00F42B73 /* NSString+IPAddress.m */, @@ -635,6 +639,7 @@ 018333E91A35746500670CD1 /* https-everywhere_rules.plist in Resources */, 01801EC31A3360F8002B4718 /* InAppSettings.bundle in Resources */, A024D5AF1ECEF10F00B28CC5 /* OnePasswordExtension.strings in Resources */, + A09A2AA52254BB2E00A3EEF0 /* InfoPlist.strings in Resources */, 01D7412C1A45F8EB007B7033 /* injected.js in Resources */, 01801EA61A32CA2A002B4718 /* Images.xcassets in Resources */, 01BFEE4A1E3D3CD60069AC83 /* urlblocker.json in Resources */, @@ -840,6 +845,15 @@ name = OnePasswordExtension.strings; sourceTree = ""; }; + A09A2AA72254BB2E00A3EEF0 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + A09A2AA62254BB2E00A3EEF0 /* en */, + A09A2AA82254BB2F00A3EEF0 /* de */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ diff --git a/Endless/Info.plist b/Endless/Info.plist index a08b5bf..e66c856 100644 --- a/Endless/Info.plist +++ b/Endless/Info.plist @@ -121,5 +121,7 @@ UIViewControllerBasedStatusBarAppearance + NSPhotoLibraryAddUsageDescription + Needed to store the selected image to your photos. diff --git a/Endless/de.lproj/InfoPlist.strings b/Endless/de.lproj/InfoPlist.strings new file mode 100644 index 0000000..a0b8a52 --- /dev/null +++ b/Endless/de.lproj/InfoPlist.strings @@ -0,0 +1,8 @@ +/* + InfoPlist.strings + Endless + + Created by Benjamin Erhart on 03.04.19. + Copyright © 2019 jcs. All rights reserved. +*/ +NSPhotoLibraryAddUsageDescription = "Nötig, um das ausgewählte Bild zu ihren Fotos zu speichern."; diff --git a/Endless/en.lproj/InfoPlist.strings b/Endless/en.lproj/InfoPlist.strings new file mode 100644 index 0000000..f7bf65b --- /dev/null +++ b/Endless/en.lproj/InfoPlist.strings @@ -0,0 +1,8 @@ +/* + InfoPlist.strings + Endless + + Created by Benjamin Erhart on 03.04.19. + Copyright © 2019 jcs. All rights reserved. +*/ +NSPhotoLibraryAddUsageDescription = "Needed to store the selected image to your photos."; From 09cc4d98f5d0dc9ff8fc903966c5a1f729773cc4 Mon Sep 17 00:00:00 2001 From: Benjamin Erhart Date: Tue, 9 Apr 2019 17:47:25 +0200 Subject: [PATCH 16/18] Improve UI for settings: "Content Policy: Strict" can't have "Allow WebRTC: Yes". When no JavaScript is run, there's no WebRTC. So mutually exclude these two. --- Endless/HostSettingsController.m | 39 +++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/Endless/HostSettingsController.m b/Endless/HostSettingsController.m index 6d49f6c..280c191 100644 --- a/Endless/HostSettingsController.m +++ b/Endless/HostSettingsController.m @@ -167,6 +167,8 @@ - (void)showDetailsForHost:(NSString *)thost XLFormDescriptor *form = [XLFormDescriptor formDescriptorWithTitle:[host hostname]]; + HostSettingsXLFormViewController *formController = [[HostSettingsXLFormViewController alloc] initWithForm:form]; + /* hostname */ { XLFormSectionDescriptor *section = [XLFormSectionDescriptor formSection]; @@ -211,7 +213,24 @@ - (void)showDetailsForHost:(NSString *)thost { XLFormRowDescriptor *row = [XLFormRowDescriptor formRowDescriptorWithTag:HOST_SETTINGS_KEY_ALLOW_WEBRTC rowType:XLFormRowDescriptorTypeSelectorActionSheet title:NSLocalizedString(@"Allow WebRTC", nil)]; [self setYesNoSelectorOptionsForSetting:HOST_SETTINGS_KEY_ALLOW_WEBRTC host:host row:row withDefault:(![host isDefault])]; - + + row.onChangeBlock = ^(XLFormOptionsObject * _Nullable oldValue, XLFormOptionsObject * _Nullable newValue, XLFormRowDescriptor * _Nonnull rowDescriptor) { + if ([newValue.formValue isEqual:HOST_SETTINGS_VALUE_YES]) { + XLFormRowDescriptor *row = [form formRowWithTag:HOST_SETTINGS_KEY_CSP]; + + if ([((XLFormOptionsObject *)row.value).formValue isEqual:HOST_SETTINGS_CSP_STRICT]) { + for (XLFormOptionsObject *opt in row.selectorOptions) { + if ([opt.valueData isEqual:HOST_SETTINGS_CSP_BLOCK_CONNECT]) { + row.value = opt; + break; + } + } + + [formController reloadFormRow: row]; + } + } + }; + section = [XLFormSectionDescriptor formSection]; [section setTitle:@""]; [section setFooterTitle:([host isDefault] @@ -308,7 +327,22 @@ - (void)showDetailsForHost:(NSString *)thost for (XLFormOptionsObject *opt in opts) if ([[opt valueData] isEqualToString:val]) [row setValue:opt]; - + + row.onChangeBlock = ^(XLFormOptionsObject * _Nullable oldValue, XLFormOptionsObject * _Nullable newValue, XLFormRowDescriptor * _Nonnull rowDescriptor) { + if ([newValue.formValue isEqual:HOST_SETTINGS_CSP_STRICT]) { + XLFormRowDescriptor *row = [form formRowWithTag:HOST_SETTINGS_KEY_ALLOW_WEBRTC]; + + for (XLFormOptionsObject *opt in row.selectorOptions) { + if ([opt.valueData isEqual:HOST_SETTINGS_VALUE_NO]) { + row.value = opt; + break; + } + } + + [formController reloadFormRow: row]; + } + }; + section = [XLFormSectionDescriptor formSection]; [section setTitle:@""]; [section setFooterTitle:([host isDefault] @@ -362,7 +396,6 @@ - (void)showDetailsForHost:(NSString *)thost } } - HostSettingsXLFormViewController *formController = [[HostSettingsXLFormViewController alloc] initWithForm:form]; [formController setDisappearCallback:^(HostSettingsXLFormViewController *form) { if (![host isDefault]) [host setHostname:[[form formValues] objectForKey:HOST_SETTINGS_KEY_HOST]]; From 6a6ac9e102a6605f000731eeb2cdb7ef37b63f97 Mon Sep 17 00:00:00 2001 From: Benjamin Erhart Date: Tue, 9 Apr 2019 18:08:50 +0200 Subject: [PATCH 17/18] Added missing localizations. --- Endless/Base.lproj/Localizable.strings | Bin 20414 -> 22112 bytes Endless/de.lproj/Localizable.strings | Bin 20950 -> 22838 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/Endless/Base.lproj/Localizable.strings b/Endless/Base.lproj/Localizable.strings index e7d16614455404be5ab546bdf485abca4e2a91b0..c44ee6486fcf2033fdf852183102c2ba6ab93f63 100644 GIT binary patch delta 1015 zcmdltpYg#O#ti{1iir%#K$yx<41@{{;XqarLl8p@*WnE$rm8} z&3`yAF^lFf zO9%3SUIUUjV170@&_FT@KvfDr8YHU=6b0!5nUTm)1SA!JRwpu40_hT<3Xs||Ae{-8 zDFCuSfu9Ks_#CjBd>){6sX*;uD<>zKi1I?50J1chA#w744bgfJs09P$NIsye(Htp? z;z;CVU{9)JAz@qq^kOq3EWix delta 41 zcmV+^0M`HDtO35C0kBX6liUStlh_LslRg9zv)l!S1hZ@lW(2cj5G)h3oF~LCVGs|& diff --git a/Endless/de.lproj/Localizable.strings b/Endless/de.lproj/Localizable.strings index cecf0de07806a2eebf428bc176b7708b6aee33ba..35b275055a1407db3ad64e1f5e74418ad70bdd56 100644 GIT binary patch delta 1154 zcmcIkO-lk%6urW<_YU3hW1s2i=ErejwQHN|4KhoUz2ZE^g2ZH`U zG|;AB;ig@2O9=J_u4_z=3USaDnOSdKKXlpH}ikv%z( zEoen)iKnj;3;Hz@({EO6<-5HLyMn(X9;Bvpjg->;XwJ`CnW>4BFX>cxX7c1Wkvacz z`qt7}D;ybvq+cS7MwL7; Date: Tue, 9 Apr 2019 18:14:54 +0200 Subject: [PATCH 18/18] Added missing localizations. --- Endless/Base.lproj/Localizable.strings | Bin 22112 -> 22310 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Endless/Base.lproj/Localizable.strings b/Endless/Base.lproj/Localizable.strings index c44ee6486fcf2033fdf852183102c2ba6ab93f63..6fd47e85d64d0f6ffb353f8ab8ec0f573dc59e7f 100644 GIT binary patch delta 116 zcmaE`hH=?C#tjNViJ1-7AS#l)PCk$cY621~3^U delta 18 acmZ3sj`6`7#tjNVlO=-HHuD5au>b%_xdvGP