Repository: cordova-ios Updated Branches: refs/heads/master f99e0be24 -> 6cc86efbb
CB-10942 - Cannot <allow-navigation href="https://foo.bar" /> for links in that site, if you have <allow-intent href="https://*" /> Project: http://git-wip-us.apache.org/repos/asf/cordova-ios/repo Commit: http://git-wip-us.apache.org/repos/asf/cordova-ios/commit/6cc86efb Tree: http://git-wip-us.apache.org/repos/asf/cordova-ios/tree/6cc86efb Diff: http://git-wip-us.apache.org/repos/asf/cordova-ios/diff/6cc86efb Branch: refs/heads/master Commit: 6cc86efbb17f59f2a9626b0867406be697fd47ab Parents: f99e0be Author: Shazron Abdullah <[email protected]> Authored: Wed Mar 23 18:45:04 2016 -0700 Committer: Shazron Abdullah <[email protected]> Committed: Mon Apr 4 17:45:46 2016 -0700 ---------------------------------------------------------------------- .../CDVIntentAndNavigationFilter.h | 9 +++ .../CDVIntentAndNavigationFilter.m | 65 ++++++++++++-------- tests/CordovaLibTests/CDVWhitelistTests.m | 18 ++++++ 3 files changed, 67 insertions(+), 25 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/6cc86efb/CordovaLib/Classes/Private/Plugins/CDVIntentAndNavigationFilter/CDVIntentAndNavigationFilter.h ---------------------------------------------------------------------- diff --git a/CordovaLib/Classes/Private/Plugins/CDVIntentAndNavigationFilter/CDVIntentAndNavigationFilter.h b/CordovaLib/Classes/Private/Plugins/CDVIntentAndNavigationFilter/CDVIntentAndNavigationFilter.h index 7f18c59..9a2ef80 100644 --- a/CordovaLib/Classes/Private/Plugins/CDVIntentAndNavigationFilter/CDVIntentAndNavigationFilter.h +++ b/CordovaLib/Classes/Private/Plugins/CDVIntentAndNavigationFilter/CDVIntentAndNavigationFilter.h @@ -18,7 +18,16 @@ */ #import "CDVPlugin.h" +#import "CDVWhitelist.h" + +typedef NS_ENUM(NSInteger, CDVIntentAndNavigationFilterValue) { + CDVIntentAndNavigationFilterValueIntentAllowed, + CDVIntentAndNavigationFilterValueNavigationAllowed, + CDVIntentAndNavigationFilterValueNoneAllowed +}; @interface CDVIntentAndNavigationFilter : CDVPlugin <NSXMLParserDelegate> ++ (CDVIntentAndNavigationFilterValue) filterUrl:(NSURL*)url intentsWhitelist:(CDVWhitelist*)intentsWhitelist navigationsWhitelist:(CDVWhitelist*)navigationsWhitelist; + @end http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/6cc86efb/CordovaLib/Classes/Private/Plugins/CDVIntentAndNavigationFilter/CDVIntentAndNavigationFilter.m ---------------------------------------------------------------------- diff --git a/CordovaLib/Classes/Private/Plugins/CDVIntentAndNavigationFilter/CDVIntentAndNavigationFilter.m b/CordovaLib/Classes/Private/Plugins/CDVIntentAndNavigationFilter/CDVIntentAndNavigationFilter.m index 365db3f..a7e2fe3 100644 --- a/CordovaLib/Classes/Private/Plugins/CDVIntentAndNavigationFilter/CDVIntentAndNavigationFilter.m +++ b/CordovaLib/Classes/Private/Plugins/CDVIntentAndNavigationFilter/CDVIntentAndNavigationFilter.m @@ -71,41 +71,56 @@ } } ++ (CDVIntentAndNavigationFilterValue) filterUrl:(NSURL*)url intentsWhitelist:(CDVWhitelist*)intentsWhitelist navigationsWhitelist:(CDVWhitelist*)navigationsWhitelist +{ + // a URL can only allow-intent OR allow-navigation, if both are specified, + // only allow-navigation is allowed + + BOOL allowNavigationsPass = [navigationsWhitelist URLIsAllowed:url logFailure:NO]; + BOOL allowIntentPass = [intentsWhitelist URLIsAllowed:url logFailure:NO]; + + if (allowNavigationsPass && allowIntentPass) { + return CDVIntentAndNavigationFilterValueNavigationAllowed; + } else if (allowNavigationsPass) { + return CDVIntentAndNavigationFilterValueNavigationAllowed; + } else if (allowIntentPass) { + return CDVIntentAndNavigationFilterValueIntentAllowed; + } + + return CDVIntentAndNavigationFilterValueNoneAllowed; +} + +- (CDVIntentAndNavigationFilterValue) filterUrl:(NSURL*)url +{ + return [[self class] filterUrl:url intentsWhitelist:self.allowIntentsWhitelist navigationsWhitelist:self.allowNavigationsWhitelist]; +} + - (BOOL)shouldOverrideLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType { NSString* allowIntents_whitelistRejectionFormatString = @"ERROR External navigation rejected - <allow-intent> not set for url='%@'"; NSString* allowNavigations_whitelistRejectionFormatString = @"ERROR Internal navigation rejected - <allow-navigation> not set for url='%@'"; NSURL* url = [request URL]; - BOOL allowNavigationsPass = NO; - NSMutableArray* errorLogs = [NSMutableArray array]; + CDVIntentAndNavigationFilterValue filterValue = [self filterUrl:url]; - switch (navigationType) { - case UIWebViewNavigationTypeLinkClicked: - // Note that the rejection strings will *only* print if - // it's a link click (and url is not whitelisted by <allow-*>) - if ([self.allowIntentsWhitelist URLIsAllowed:url logFailure:NO]) { - // the url *is* in a <allow-intent> tag, push to the system + switch (filterValue) { + case CDVIntentAndNavigationFilterValueNavigationAllowed: + return YES; + case CDVIntentAndNavigationFilterValueIntentAllowed: + // only allow-intent if it's a UIWebViewNavigationTypeLinkClicked (anchor tag) + if (UIWebViewNavigationTypeLinkClicked == navigationType) { [[UIApplication sharedApplication] openURL:url]; - return NO; - } else { - [errorLogs addObject:[NSString stringWithFormat:allowIntents_whitelistRejectionFormatString, [url absoluteString]]]; } - // fall through, to check whether you can load this in the webview - default: - // check whether we can internally navigate to this url - allowNavigationsPass = [self.allowNavigationsWhitelist URLIsAllowed:url logFailure:NO]; - // log all failures only when this last filter fails - if (!allowNavigationsPass){ - [errorLogs addObject:[NSString stringWithFormat:allowNavigations_whitelistRejectionFormatString, [url absoluteString]]]; - - // this is the last filter and it failed, now print out all previous error logs - for (NSString* errorLog in errorLogs) { - NSLog(@"%@", errorLog); - } + // consume the request (i.e. no error) if it wasn't a UIWebViewNavigationTypeLinkClicked + return NO; + case CDVIntentAndNavigationFilterValueNoneAllowed: + // allow-navigation attempt failed for sure + NSLog(@"%@", [NSString stringWithFormat:allowNavigations_whitelistRejectionFormatString, [url absoluteString]]); + // anchor tag link means it was an allow-intent attempt that failed as well + if (UIWebViewNavigationTypeLinkClicked == navigationType) { + NSLog(@"%@", [NSString stringWithFormat:allowIntents_whitelistRejectionFormatString, [url absoluteString]]); } - - return allowNavigationsPass; + return NO; } } http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/6cc86efb/tests/CordovaLibTests/CDVWhitelistTests.m ---------------------------------------------------------------------- diff --git a/tests/CordovaLibTests/CDVWhitelistTests.m b/tests/CordovaLibTests/CDVWhitelistTests.m index 5f979c0..9f83f2a 100644 --- a/tests/CordovaLibTests/CDVWhitelistTests.m +++ b/tests/CordovaLibTests/CDVWhitelistTests.m @@ -20,6 +20,7 @@ #import <XCTest/XCTest.h> #import <Cordova/CDVWhitelist.h> +#import "CDVIntentAndNavigationFilter.h" @interface CDVWhitelistTests : XCTestCase @end @@ -280,4 +281,21 @@ XCTAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://user:[email protected]"]]); } +- (void)testAllowIntentsAndNavigations +{ + NSArray* allowIntents = @[ @"https://*" ]; + NSArray* allowNavigations = @[ @"https://*.apache.org" ]; + + CDVWhitelist* intentsWhitelist = [[CDVWhitelist alloc] initWithArray:allowIntents]; + CDVWhitelist* navigationsWhitelist = [[CDVWhitelist alloc] initWithArray:allowNavigations]; + + // Test allow-navigation superceding allow-intent + XCTAssertEqual([CDVIntentAndNavigationFilter filterUrl:[NSURL URLWithString:@"https://apache.org/foo.html"] intentsWhitelist:intentsWhitelist navigationsWhitelist:navigationsWhitelist], CDVIntentAndNavigationFilterValueNavigationAllowed); + // Test wildcard https as allow-intent + XCTAssertEqual([CDVIntentAndNavigationFilter filterUrl:[NSURL URLWithString:@"https://google.com"] intentsWhitelist:intentsWhitelist navigationsWhitelist:navigationsWhitelist], CDVIntentAndNavigationFilterValueIntentAllowed); + // Test http (not allowed in either) + XCTAssertEqual([CDVIntentAndNavigationFilter filterUrl:[NSURL URLWithString:@"http://google.com"] intentsWhitelist:intentsWhitelist navigationsWhitelist:navigationsWhitelist], CDVIntentAndNavigationFilterValueNoneAllowed); +} + + @end --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
