diff --git a/packages/flutter_tools/lib/src/ios/xcodeproj.dart b/packages/flutter_tools/lib/src/ios/xcodeproj.dart index 011454bc00..bb81534287 100644 --- a/packages/flutter_tools/lib/src/ios/xcodeproj.dart +++ b/packages/flutter_tools/lib/src/ios/xcodeproj.dart @@ -412,21 +412,6 @@ class XcodeProjectBuildContext { } } -/// The settings that are relevant for setting up universal links -@immutable -class XcodeUniversalLinkSettings { - const XcodeUniversalLinkSettings({ - this.bundleIdentifier, - this.teamIdentifier, - this.associatedDomains = const [], - }); - - final String? bundleIdentifier; - final String? teamIdentifier; - final List associatedDomains; -} - - /// Information about an Xcode project. /// /// Represents the output of `xcodebuild -list`. diff --git a/packages/flutter_tools/lib/src/project.dart b/packages/flutter_tools/lib/src/project.dart index 6ded1d332f..24897e311d 100644 --- a/packages/flutter_tools/lib/src/project.dart +++ b/packages/flutter_tools/lib/src/project.dart @@ -121,6 +121,9 @@ class FlutterProject { /// The location of this project. final Directory directory; + /// The location of the build folder. + Directory get buildDirectory => directory.childDirectory('build'); + /// The manifest of this project. final FlutterManifest manifest; @@ -657,7 +660,7 @@ $javaGradleCompatUrl /// The build directory where the Android artifacts are placed. Directory get buildDirectory { - return parent.directory.childDirectory('build'); + return parent.buildDirectory; } Future ensureReadyForPlatformSpecificTooling({DeprecationBehavior deprecationBehavior = DeprecationBehavior.none}) async { diff --git a/packages/flutter_tools/lib/src/vmservice.dart b/packages/flutter_tools/lib/src/vmservice.dart index 531e88408e..78a5b92bd7 100644 --- a/packages/flutter_tools/lib/src/vmservice.dart +++ b/packages/flutter_tools/lib/src/vmservice.dart @@ -16,7 +16,6 @@ import 'cache.dart'; import 'convert.dart'; import 'device.dart'; import 'globals.dart' as globals; -import 'ios/xcodeproj.dart'; import 'project.dart'; import 'version.dart'; @@ -41,8 +40,6 @@ const String kFlutterVersionServiceName = 'flutterVersion'; const String kCompileExpressionServiceName = 'compileExpression'; const String kFlutterMemoryInfoServiceName = 'flutterMemoryInfo'; const String kFlutterGetSkSLServiceName = 'flutterGetSkSL'; -const String kFlutterGetIOSBuildOptionsServiceName = 'flutterGetIOSBuildOptions'; -const String kFlutterGetIOSUniversalLinkSettingsServiceName = 'flutterGetIOSUniversalLinkSettings'; /// The error response code from an unrecoverable compilation failure. const int kIsolateReloadBarred = 1005; @@ -315,49 +312,6 @@ Future setUpVmService({ registrationRequests.add(vmService.registerService(kFlutterGetSkSLServiceName, kFlutterToolAlias)); } - if (flutterProject != null) { - vmService.registerServiceCallback(kFlutterGetIOSBuildOptionsServiceName, (Map params) async { - final XcodeProjectInfo? info = await flutterProject.ios.projectInfo(); - if (info == null) { - return { - 'result': { - kResultType: kResultTypeSuccess, - }, - }; - } - return { - 'result': { - kResultType: kResultTypeSuccess, - 'targets': info.targets, - 'schemes': info.schemes, - 'buildConfigurations': info.buildConfigurations, - }, - }; - }); - registrationRequests.add( - vmService.registerService(kFlutterGetIOSBuildOptionsServiceName, kFlutterToolAlias), - ); - - vmService.registerServiceCallback(kFlutterGetIOSUniversalLinkSettingsServiceName, (Map params) async { - final XcodeUniversalLinkSettings settings = await flutterProject.ios.universalLinkSettings( - configuration: params['configuration']! as String, - scheme: params['scheme']! as String, - target: params['target']! as String, - ); - return { - 'result': { - kResultType: kResultTypeSuccess, - 'bundleIdentifier': settings.bundleIdentifier ?? '', - 'teamIdentifier': settings.teamIdentifier ?? '', - 'associatedDomains': settings.associatedDomains, - }, - }; - }); - registrationRequests.add( - vmService.registerService(kFlutterGetIOSUniversalLinkSettingsServiceName, kFlutterToolAlias), - ); - } - if (printStructuredErrorLogMethod != null) { vmService.onExtensionEvent.listen(printStructuredErrorLogMethod); registrationRequests.add(vmService diff --git a/packages/flutter_tools/lib/src/xcode_project.dart b/packages/flutter_tools/lib/src/xcode_project.dart index add59a60b1..c95ca87c43 100644 --- a/packages/flutter_tools/lib/src/xcode_project.dart +++ b/packages/flutter_tools/lib/src/xcode_project.dart @@ -7,6 +7,7 @@ import 'base/file_system.dart'; import 'base/utils.dart'; import 'build_info.dart'; import 'bundle.dart' as bundle; +import 'convert.dart'; import 'flutter_plugins.dart'; import 'globals.dart' as globals; import 'ios/code_signing.dart'; @@ -214,7 +215,11 @@ class IosProject extends XcodeBasedProject { return parent.isModule || _editableDirectory.existsSync(); } - Future universalLinkSettings({ + /// Output universal link related project settings of the iOS sub-project into + /// a json file. + /// + /// The return future will resolve to string path to the output file. + Future outputUniversalLinkSettings({ required String configuration, required String scheme, required String target, @@ -224,12 +229,16 @@ class IosProject extends XcodeBasedProject { scheme: scheme, target: target, ); - - return XcodeUniversalLinkSettings( - bundleIdentifier: await _productBundleIdentifierWithBuildContext(context), - teamIdentifier: await _getTeamIdentifier(context), - associatedDomains: await _getAssociatedDomains(context), - ); + final File file = await parent.buildDirectory + .childDirectory('deeplink_data') + .childFile('universal-link-settings-$configuration-$scheme-$target.json') + .create(recursive: true); + await file.writeAsString(jsonEncode({ + 'bundleIdentifier': await _productBundleIdentifierWithBuildContext(context), + 'teamIdentifier': await _getTeamIdentifier(context), + 'associatedDomains': await _getAssociatedDomains(context), + })); + return file.absolute.path; } /// The product bundle identifier of the host app, or null if not set or if diff --git a/packages/flutter_tools/test/general.shard/project_test.dart b/packages/flutter_tools/test/general.shard/project_test.dart index e80ba79de5..759ec7eae8 100644 --- a/packages/flutter_tools/test/general.shard/project_test.dart +++ b/packages/flutter_tools/test/general.shard/project_test.dart @@ -751,13 +751,16 @@ apply plugin: 'kotlin-android' 'applinks:example2.com', ], ); - final XcodeUniversalLinkSettings settings = await project.ios.universalLinkSettings( + final String outputFilePath = await project.ios.outputUniversalLinkSettings( target: 'Runner', scheme: 'Debug', configuration: 'config', ); + final File outputFile = fs.file(outputFilePath); + final Map json = jsonDecode(outputFile.readAsStringSync()) as Map; + expect( - settings.associatedDomains, + json['associatedDomains'], unorderedEquals( [ 'example.com', @@ -765,8 +768,8 @@ apply plugin: 'kotlin-android' ], ), ); - expect(settings.teamIdentifier, 'ABC'); - expect(settings.bundleIdentifier, 'io.flutter.someProject.suffix'); + expect(json['teamIdentifier'], 'ABC'); + expect(json['bundleIdentifier'], 'io.flutter.someProject.suffix'); }); testWithMocks('can handle entitlement file in nested directory structure.', () async { @@ -796,13 +799,16 @@ apply plugin: 'kotlin-android' 'applinks:example2.com', ], ); - final XcodeUniversalLinkSettings settings = await project.ios.universalLinkSettings( + + final String outputFilePath = await project.ios.outputUniversalLinkSettings( target: 'Runner', scheme: 'Debug', configuration: 'config', ); + final File outputFile = fs.file(outputFilePath); + final Map json = jsonDecode(outputFile.readAsStringSync()) as Map; expect( - settings.associatedDomains, + json['associatedDomains'], unorderedEquals( [ 'example.com', @@ -810,8 +816,8 @@ apply plugin: 'kotlin-android' ], ), ); - expect(settings.teamIdentifier, 'ABC'); - expect(settings.bundleIdentifier, 'io.flutter.someProject.suffix'); + expect(json['teamIdentifier'], 'ABC'); + expect(json['bundleIdentifier'], 'io.flutter.someProject.suffix'); }); testWithMocks('return empty when no entitlement', () async { @@ -830,13 +836,16 @@ apply plugin: 'kotlin-android' }; xcodeProjectInterpreter.xcodeProjectInfo = XcodeProjectInfo([], [], ['Runner'], logger); testPlistUtils.setProperty(PlistParser.kCFBundleIdentifierKey, r'$(PRODUCT_BUNDLE_IDENTIFIER)'); - final XcodeUniversalLinkSettings settings = await project.ios.universalLinkSettings( + final String outputFilePath = await project.ios.outputUniversalLinkSettings( target: 'Runner', scheme: 'Debug', configuration: 'config', ); - expect(settings.teamIdentifier, 'ABC'); - expect(settings.bundleIdentifier, 'io.flutter.someProject'); + final File outputFile = fs.file(outputFilePath); + final Map json = jsonDecode(outputFile.readAsStringSync()) as Map; + expect(json['teamIdentifier'], 'ABC'); + expect(json['bundleIdentifier'], 'io.flutter.someProject'); + expect(json['associatedDomains'], unorderedEquals([])); }); }); diff --git a/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart b/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart index 96105be45b..01a1f098ed 100644 --- a/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart +++ b/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart @@ -74,14 +74,6 @@ const List kAttachIsolateExpectations = 'service': kFlutterMemoryInfoServiceName, 'alias': kFlutterToolAlias, }), - FakeVmServiceRequest(method: 'registerService', args: { - 'service': kFlutterGetIOSBuildOptionsServiceName, - 'alias': kFlutterToolAlias, - }), - FakeVmServiceRequest(method: 'registerService', args: { - 'service': kFlutterGetIOSUniversalLinkSettingsServiceName, - 'alias': kFlutterToolAlias, - }), FakeVmServiceRequest( method: 'streamListen', args: { diff --git a/packages/flutter_tools/test/general.shard/vmservice_test.dart b/packages/flutter_tools/test/general.shard/vmservice_test.dart index d4f2fc3371..73e710c656 100644 --- a/packages/flutter_tools/test/general.shard/vmservice_test.dart +++ b/packages/flutter_tools/test/general.shard/vmservice_test.dart @@ -9,8 +9,6 @@ import 'package:flutter_tools/src/base/io.dart' as io; import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/convert.dart'; import 'package:flutter_tools/src/device.dart'; -import 'package:flutter_tools/src/ios/xcodeproj.dart'; -import 'package:flutter_tools/src/project.dart'; import 'package:flutter_tools/src/vmservice.dart'; import 'package:test/fake.dart'; import 'package:vm_service/vm_service.dart' as vm_service; @@ -85,17 +83,6 @@ void main() { expect(mockVMService.services, containsPair(kFlutterMemoryInfoServiceName, kFlutterToolAlias)); }); - testWithoutContext('VmService registers flutterGetIOSBuildOptions service', () async { - final MockVMService mockVMService = MockVMService(); - final FlutterProject mockedFlutterProject = MockFlutterProject(); - await setUpVmService( - flutterProject: mockedFlutterProject, - vmService: mockVMService, - ); - - expect(mockVMService.services, containsPair(kFlutterGetIOSBuildOptionsServiceName, kFlutterToolAlias)); - }); - testWithoutContext('VM Service registers flutterGetSkSL service', () async { final MockVMService mockVMService = MockVMService(); await setUpVmService( @@ -277,50 +264,6 @@ void main() { ])); }); - testWithoutContext('VmService forward flutterGetIOSBuildOptions request and response correctly', () async { - final MockVMService vmService = MockVMService(); - final XcodeProjectInfo expectedProjectInfo = XcodeProjectInfo( - ['target1', 'target2'], - ['config1', 'config2'], - ['scheme1', 'scheme2'], - MockLogger(), - ); - final FlutterProject mockedFlutterProject = MockFlutterProject( - mockedIos: MockIosProject(mockedInfo: expectedProjectInfo), - ); - await setUpVmService( - flutterProject: mockedFlutterProject, - vmService: vmService - ); - final vm_service.ServiceCallback cb = vmService.serviceCallBacks[kFlutterGetIOSBuildOptionsServiceName]!; - - final Map response = await cb({}); - final Map result = response['result']! as Map; - expect(result[kResultType], kResultTypeSuccess); - expect(result['targets'], expectedProjectInfo.targets); - expect(result['buildConfigurations'], expectedProjectInfo.buildConfigurations); - expect(result['schemes'], expectedProjectInfo.schemes); - }); - - testWithoutContext('VmService forward flutterGetIOSBuildOptions request and response correctly when no iOS project', () async { - final MockVMService vmService = MockVMService(); - final FlutterProject mockedFlutterProject = MockFlutterProject( - mockedIos: MockIosProject(), - ); - await setUpVmService( - flutterProject: mockedFlutterProject, - vmService: vmService - ); - final vm_service.ServiceCallback cb = vmService.serviceCallBacks[kFlutterGetIOSBuildOptionsServiceName]!; - - final Map response = await cb({}); - final Map result = response['result']! as Map; - expect(result[kResultType], kResultTypeSuccess); - expect(result['targets'], isNull); - expect(result['buildConfigurations'], isNull); - expect(result['schemes'], isNull); - }); - testWithoutContext('runInView forwards arguments correctly', () async { final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost( requests: [ @@ -908,26 +851,6 @@ void main() { }); } -class MockFlutterProject extends Fake implements FlutterProject { - MockFlutterProject({ - IosProject? mockedIos, - }) : ios = mockedIos ?? MockIosProject(); - - @override - final IosProject ios; -} - -class MockIosProject extends Fake implements IosProject { - MockIosProject({this.mockedInfo}); - - final XcodeProjectInfo? mockedInfo; - - @override - Future projectInfo() async => mockedInfo; -} - -class MockLogger extends Fake implements Logger { } - class MockVMService extends Fake implements vm_service.VmService { final Map services = {}; final Map serviceCallBacks = {}; diff --git a/packages/flutter_tools/test/integration.shard/vmservice_integration_test.dart b/packages/flutter_tools/test/integration.shard/vmservice_integration_test.dart index 7768150930..45a0e86ebd 100644 --- a/packages/flutter_tools/test/integration.shard/vmservice_integration_test.dart +++ b/packages/flutter_tools/test/integration.shard/vmservice_integration_test.dart @@ -59,12 +59,6 @@ void main() { expect(response.type, 'Success'); }); - testWithoutContext('flutterGetIOSBuildOptions can be called', () async { - final Response response = - await vmService.callServiceExtension('s0.flutterGetIOSBuildOptions'); - expect(response.type, 'Success'); - }); - testWithoutContext('reloadSources can be called', () async { final VM vm = await vmService.getVM(); final IsolateRef? isolateRef = vm.isolates?.first;