From 0b3b8cd5516d77658135ba4b830915c7ff43500d Mon Sep 17 00:00:00 2001 From: chunhtai <47866232+chunhtai@users.noreply.github.com> Date: Thu, 31 Aug 2023 14:50:54 -0700 Subject: [PATCH] =?UTF-8?q?Removes=20ios=20universal=20link=20vmservices?= =?UTF-8?q?=20and=20let=20xcodeproject=20to=20dump=20js=E2=80=A6=20(#13370?= =?UTF-8?q?9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …on file The deeplink validation tool will become an static app so it can't no longer access vm services. The goal will be then to turn them into flutter analyze command similar to `flutter analyze --android --[options]` that static app can use on. This pr only removes vm services and turn the api to dump a output file instead of printing everything to stdout. --- .../flutter_tools/lib/src/ios/xcodeproj.dart | 15 ---- packages/flutter_tools/lib/src/project.dart | 5 +- packages/flutter_tools/lib/src/vmservice.dart | 46 ----------- .../flutter_tools/lib/src/xcode_project.dart | 23 ++++-- .../test/general.shard/project_test.dart | 31 +++++--- .../resident_web_runner_test.dart | 8 -- .../test/general.shard/vmservice_test.dart | 77 ------------------- .../vmservice_integration_test.dart | 6 -- 8 files changed, 40 insertions(+), 171 deletions(-) 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;