Removes ios universal link vmservices and let xcodeproject to dump js… (#133709)

…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.
This commit is contained in:
chunhtai 2023-08-31 14:50:54 -07:00 committed by GitHub
parent e6e44de33c
commit 0b3b8cd551
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 40 additions and 171 deletions

View File

@ -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 <String>[],
});
final String? bundleIdentifier;
final String? teamIdentifier;
final List<String> associatedDomains;
}
/// Information about an Xcode project.
///
/// Represents the output of `xcodebuild -list`.

View File

@ -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<void> ensureReadyForPlatformSpecificTooling({DeprecationBehavior deprecationBehavior = DeprecationBehavior.none}) async {

View File

@ -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<vm_service.VmService> setUpVmService({
registrationRequests.add(vmService.registerService(kFlutterGetSkSLServiceName, kFlutterToolAlias));
}
if (flutterProject != null) {
vmService.registerServiceCallback(kFlutterGetIOSBuildOptionsServiceName, (Map<String, Object?> params) async {
final XcodeProjectInfo? info = await flutterProject.ios.projectInfo();
if (info == null) {
return <String, Object>{
'result': <String, Object>{
kResultType: kResultTypeSuccess,
},
};
}
return <String, Object>{
'result': <String, Object>{
kResultType: kResultTypeSuccess,
'targets': info.targets,
'schemes': info.schemes,
'buildConfigurations': info.buildConfigurations,
},
};
});
registrationRequests.add(
vmService.registerService(kFlutterGetIOSBuildOptionsServiceName, kFlutterToolAlias),
);
vmService.registerServiceCallback(kFlutterGetIOSUniversalLinkSettingsServiceName, (Map<String, Object?> 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 <String, Object>{
'result': <String, Object>{
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

View File

@ -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<XcodeUniversalLinkSettings> 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<String> 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(<String, Object?>{
'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

View File

@ -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<String, Object?> json = jsonDecode(outputFile.readAsStringSync()) as Map<String, Object?>;
expect(
settings.associatedDomains,
json['associatedDomains'],
unorderedEquals(
<String>[
'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<String, Object?> json = jsonDecode(outputFile.readAsStringSync()) as Map<String, Object?>;
expect(
settings.associatedDomains,
json['associatedDomains'],
unorderedEquals(
<String>[
'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(<String>[], <String>[], <String>['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<String, Object?> json = jsonDecode(outputFile.readAsStringSync()) as Map<String, Object?>;
expect(json['teamIdentifier'], 'ABC');
expect(json['bundleIdentifier'], 'io.flutter.someProject');
expect(json['associatedDomains'], unorderedEquals(<String>[]));
});
});

View File

@ -74,14 +74,6 @@ const List<VmServiceExpectation> kAttachIsolateExpectations =
'service': kFlutterMemoryInfoServiceName,
'alias': kFlutterToolAlias,
}),
FakeVmServiceRequest(method: 'registerService', args: <String, Object>{
'service': kFlutterGetIOSBuildOptionsServiceName,
'alias': kFlutterToolAlias,
}),
FakeVmServiceRequest(method: 'registerService', args: <String, Object>{
'service': kFlutterGetIOSUniversalLinkSettingsServiceName,
'alias': kFlutterToolAlias,
}),
FakeVmServiceRequest(
method: 'streamListen',
args: <String, Object>{

View File

@ -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(
<String>['target1', 'target2'],
<String>['config1', 'config2'],
<String>['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<String, dynamic> response = await cb(<String, dynamic>{});
final Map<String, dynamic> result = response['result']! as Map<String, dynamic>;
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<String, dynamic> response = await cb(<String, dynamic>{});
final Map<String, dynamic> result = response['result']! as Map<String, dynamic>;
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: <VmServiceExpectation>[
@ -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<XcodeProjectInfo?> projectInfo() async => mockedInfo;
}
class MockLogger extends Fake implements Logger { }
class MockVMService extends Fake implements vm_service.VmService {
final Map<String, String> services = <String, String>{};
final Map<String, vm_service.ServiceCallback> serviceCallBacks = <String, vm_service.ServiceCallback>{};

View File

@ -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;