mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Enable iOS plumbing for network security and add tests (#20492)
This commit is contained in:
parent
3ebcde6a17
commit
3aff256928
@ -920,6 +920,7 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterBinaryM
|
||||
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterCallbackCache.mm
|
||||
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterCallbackCache_Internal.h
|
||||
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm
|
||||
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProjectTest.mm
|
||||
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h
|
||||
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm
|
||||
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterEnginePlatformViewTest.mm
|
||||
|
||||
@ -208,6 +208,7 @@ shared_library("ios_test_flutter") {
|
||||
]
|
||||
sources = [
|
||||
"framework/Source/FlutterBinaryMessengerRelayTest.mm",
|
||||
"framework/Source/FlutterDartProjectTest.mm",
|
||||
"framework/Source/FlutterEngineTest.mm",
|
||||
"framework/Source/FlutterPluginAppLifeCycleDelegateTest.m",
|
||||
"framework/Source/FlutterTextInputPluginTest.m",
|
||||
|
||||
@ -26,42 +26,6 @@ extern const intptr_t kPlatformStrongDillSize;
|
||||
|
||||
static const char* kApplicationKernelSnapshotFileName = "kernel_blob.bin";
|
||||
|
||||
// TODO(mehmetf): Announce this since it is breaking change then enable it.
|
||||
// static NSString* DomainNetworkPolicy(NSDictionary* appTransportSecurity) {
|
||||
// if (appTransportSecurity == nil) {
|
||||
// return @"";
|
||||
// }
|
||||
// //
|
||||
// https://developer.apple.com/documentation/bundleresources/information_property_list/nsapptransportsecurity/nsexceptiondomains
|
||||
// NSDictionary* exceptionDomains = [appTransportSecurity objectForKey:@"NSExceptionDomains"];
|
||||
// if (exceptionDomains == nil) {
|
||||
// return @"";
|
||||
// }
|
||||
// NSMutableArray* networkConfigArray = [[NSMutableArray alloc] init];
|
||||
// for (NSString* domain in exceptionDomains) {
|
||||
// NSDictionary* domainConfiguration = [exceptionDomains objectForKey:domain];
|
||||
// BOOL includesSubDomains =
|
||||
// [[domainConfiguration objectForKey:@"NSIncludesSubdomains"] boolValue];
|
||||
// BOOL allowsCleartextCommunication =
|
||||
// [[domainConfiguration objectForKey:@"NSExceptionAllowsInsecureHTTPLoads"] boolValue];
|
||||
// [networkConfigArray addObject:[NSArray arrayWithObjects:domain, includesSubDomains,
|
||||
// allowsCleartextCommunication, nil]];
|
||||
// }
|
||||
// NSData* jsonData = [NSJSONSerialization dataWithJSONObject:networkConfigArray
|
||||
// options:0
|
||||
// error:NULL];
|
||||
// return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
||||
// }
|
||||
|
||||
// TODO(mehmetf): Announce this since it is breaking change then enable it.
|
||||
// static bool AllowsArbitraryLoads(NSDictionary* appTransportSecurity) {
|
||||
// if (appTransportSecurity != nil) {
|
||||
// return [[appTransportSecurity objectForKey:@"NSAllowsArbitraryLoads"] boolValue];
|
||||
// } else {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
|
||||
static flutter::Settings DefaultSettingsForProcess(NSBundle* bundle = nil) {
|
||||
auto command_line = flutter::CommandLineFromNSProcessInfo();
|
||||
|
||||
@ -168,12 +132,19 @@ static flutter::Settings DefaultSettingsForProcess(NSBundle* bundle = nil) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(mehmetf): Announce this since it is breaking change then enable it.
|
||||
// Domain network configuration
|
||||
// NSDictionary* appTransportSecurity =
|
||||
// [mainBundle objectForInfoDictionaryKey:@"NSAppTransportSecurity"];
|
||||
// settings.may_insecurely_connect_to_all_domains = AllowsArbitraryLoads(appTransportSecurity);
|
||||
// settings.domain_network_policy = DomainNetworkPolicy(appTransportSecurity).UTF8String;
|
||||
NSDictionary* appTransportSecurity =
|
||||
[mainBundle objectForInfoDictionaryKey:@"NSAppTransportSecurity"];
|
||||
settings.may_insecurely_connect_to_all_domains =
|
||||
[FlutterDartProject allowsArbitraryLoads:appTransportSecurity];
|
||||
settings.domain_network_policy =
|
||||
[FlutterDartProject domainNetworkPolicy:appTransportSecurity].UTF8String;
|
||||
|
||||
// TODO(mehmetf): We need to announce this change since it is breaking.
|
||||
// Remove these two lines after we announce and we know which release this is
|
||||
// going to be part of.
|
||||
settings.may_insecurely_connect_to_all_domains = true;
|
||||
settings.domain_network_policy = "";
|
||||
|
||||
#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
|
||||
// There are no ownership concerns here as all mappings are owned by the
|
||||
@ -262,6 +233,34 @@ static flutter::Settings DefaultSettingsForProcess(NSBundle* bundle = nil) {
|
||||
return flutterAssetsName;
|
||||
}
|
||||
|
||||
+ (NSString*)domainNetworkPolicy:(NSDictionary*)appTransportSecurity {
|
||||
// https://developer.apple.com/documentation/bundleresources/information_property_list/nsapptransportsecurity/nsexceptiondomains
|
||||
NSDictionary* exceptionDomains = [appTransportSecurity objectForKey:@"NSExceptionDomains"];
|
||||
if (exceptionDomains == nil) {
|
||||
return @"";
|
||||
}
|
||||
NSMutableArray* networkConfigArray = [[NSMutableArray alloc] init];
|
||||
for (NSString* domain in exceptionDomains) {
|
||||
NSDictionary* domainConfiguration = [exceptionDomains objectForKey:domain];
|
||||
// Default value is false.
|
||||
bool includesSubDomains =
|
||||
[[domainConfiguration objectForKey:@"NSIncludesSubdomains"] boolValue];
|
||||
bool allowsCleartextCommunication =
|
||||
[[domainConfiguration objectForKey:@"NSExceptionAllowsInsecureHTTPLoads"] boolValue];
|
||||
[networkConfigArray addObject:@[
|
||||
domain, includesSubDomains ? @YES : @NO, allowsCleartextCommunication ? @YES : @NO
|
||||
]];
|
||||
}
|
||||
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:networkConfigArray
|
||||
options:0
|
||||
error:NULL];
|
||||
return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
||||
}
|
||||
|
||||
+ (bool)allowsArbitraryLoads:(NSDictionary*)appTransportSecurity {
|
||||
return [[appTransportSecurity objectForKey:@"NSAllowsArbitraryLoads"] boolValue];
|
||||
}
|
||||
|
||||
+ (NSString*)lookupKeyForAsset:(NSString*)asset {
|
||||
return [self lookupKeyForAsset:asset fromBundle:nil];
|
||||
}
|
||||
|
||||
@ -0,0 +1,85 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h"
|
||||
|
||||
FLUTTER_ASSERT_ARC
|
||||
|
||||
@interface FlutterDartProjectTest : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation FlutterDartProjectTest
|
||||
|
||||
- (void)setUp {
|
||||
}
|
||||
|
||||
- (void)tearDown {
|
||||
}
|
||||
|
||||
- (void)testMainBundleSettingsAreCorrectlyParsed {
|
||||
NSBundle* mainBundle = [NSBundle mainBundle];
|
||||
NSDictionary* appTransportSecurity =
|
||||
[mainBundle objectForInfoDictionaryKey:@"NSAppTransportSecurity"];
|
||||
XCTAssertTrue([FlutterDartProject allowsArbitraryLoads:appTransportSecurity]);
|
||||
XCTAssertEqualObjects(
|
||||
@"[[\"invalid-site.com\",true,false],[\"sub.invalid-site.com\",false,false]]",
|
||||
[FlutterDartProject domainNetworkPolicy:appTransportSecurity]);
|
||||
}
|
||||
|
||||
- (void)testEmptySettingsAreCorrect {
|
||||
XCTAssertFalse([FlutterDartProject allowsArbitraryLoads:[[NSDictionary alloc] init]]);
|
||||
XCTAssertEqualObjects(@"", [FlutterDartProject domainNetworkPolicy:[[NSDictionary alloc] init]]);
|
||||
}
|
||||
|
||||
- (void)testAllowsArbitraryLoads {
|
||||
XCTAssertFalse([FlutterDartProject allowsArbitraryLoads:@{@"NSAllowsArbitraryLoads" : @false}]);
|
||||
XCTAssertTrue([FlutterDartProject allowsArbitraryLoads:@{@"NSAllowsArbitraryLoads" : @true}]);
|
||||
}
|
||||
|
||||
- (void)testProperlyFormedExceptionDomains {
|
||||
NSDictionary* domainInfoOne = @{
|
||||
@"NSIncludesSubdomains" : @false,
|
||||
@"NSExceptionAllowsInsecureHTTPLoads" : @true,
|
||||
@"NSExceptionMinimumTLSVersion" : @"4.0"
|
||||
};
|
||||
NSDictionary* domainInfoTwo = @{
|
||||
@"NSIncludesSubdomains" : @true,
|
||||
@"NSExceptionAllowsInsecureHTTPLoads" : @false,
|
||||
@"NSExceptionMinimumTLSVersion" : @"4.0"
|
||||
};
|
||||
NSDictionary* domainInfoThree = @{
|
||||
@"NSIncludesSubdomains" : @false,
|
||||
@"NSExceptionAllowsInsecureHTTPLoads" : @true,
|
||||
@"NSExceptionMinimumTLSVersion" : @"4.0"
|
||||
};
|
||||
NSDictionary* exceptionDomains = @{
|
||||
@"domain.name" : domainInfoOne,
|
||||
@"sub.domain.name" : domainInfoTwo,
|
||||
@"sub.two.domain.name" : domainInfoThree
|
||||
};
|
||||
NSDictionary* appTransportSecurity = @{@"NSExceptionDomains" : exceptionDomains};
|
||||
XCTAssertEqualObjects(@"[[\"domain.name\",false,true],[\"sub.domain.name\",true,false],"
|
||||
@"[\"sub.two.domain.name\",false,true]]",
|
||||
[FlutterDartProject domainNetworkPolicy:appTransportSecurity]);
|
||||
}
|
||||
|
||||
- (void)testExceptionDomainsWithMissingInfo {
|
||||
NSDictionary* domainInfoOne = @{@"NSExceptionMinimumTLSVersion" : @"4.0"};
|
||||
NSDictionary* domainInfoTwo = @{
|
||||
@"NSIncludesSubdomains" : @true,
|
||||
};
|
||||
NSDictionary* domainInfoThree = @{};
|
||||
NSDictionary* exceptionDomains = @{
|
||||
@"domain.name" : domainInfoOne,
|
||||
@"sub.domain.name" : domainInfoTwo,
|
||||
@"sub.two.domain.name" : domainInfoThree
|
||||
};
|
||||
NSDictionary* appTransportSecurity = @{@"NSExceptionDomains" : exceptionDomains};
|
||||
XCTAssertEqualObjects(@"[[\"domain.name\",false,false],[\"sub.domain.name\",true,false],"
|
||||
@"[\"sub.two.domain.name\",false,false]]",
|
||||
[FlutterDartProject domainNetworkPolicy:appTransportSecurity]);
|
||||
}
|
||||
|
||||
@end
|
||||
@ -23,6 +23,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
libraryOrNil:(nullable NSString*)dartLibraryOrNil;
|
||||
|
||||
+ (NSString*)flutterAssetsName:(NSBundle*)bundle;
|
||||
+ (NSString*)domainNetworkPolicy:(NSDictionary*)appTransportSecurity;
|
||||
+ (bool)allowsArbitraryLoads:(NSDictionary*)appTransportSecurity;
|
||||
|
||||
/**
|
||||
* The embedder can specify data that the isolate can request synchronously on launch. Engines
|
||||
|
||||
@ -24,6 +24,26 @@
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
<key>NSExceptionDomains</key>
|
||||
<dict>
|
||||
<key>invalid-site.com</key>
|
||||
<dict>
|
||||
<key>NSIncludesSubdomains</key>
|
||||
<true/>
|
||||
<key>NSThirdPartyExceptionAllowsInsecureHTTPLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>sub.invalid-site.com</key>
|
||||
<dict>
|
||||
<key>NSThirdPartyExceptionAllowsInsecureHTTPLoads</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user