Unverified Commit 0b3b8cd5 authored by chunhtai's avatar chunhtai Committed by GitHub

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.
parent e6e44de3
...@@ -412,21 +412,6 @@ class XcodeProjectBuildContext { ...@@ -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. /// Information about an Xcode project.
/// ///
/// Represents the output of `xcodebuild -list`. /// Represents the output of `xcodebuild -list`.
......
...@@ -121,6 +121,9 @@ class FlutterProject { ...@@ -121,6 +121,9 @@ class FlutterProject {
/// The location of this project. /// The location of this project.
final Directory directory; final Directory directory;
/// The location of the build folder.
Directory get buildDirectory => directory.childDirectory('build');
/// The manifest of this project. /// The manifest of this project.
final FlutterManifest manifest; final FlutterManifest manifest;
...@@ -657,7 +660,7 @@ $javaGradleCompatUrl ...@@ -657,7 +660,7 @@ $javaGradleCompatUrl
/// The build directory where the Android artifacts are placed. /// The build directory where the Android artifacts are placed.
Directory get buildDirectory { Directory get buildDirectory {
return parent.directory.childDirectory('build'); return parent.buildDirectory;
} }
Future<void> ensureReadyForPlatformSpecificTooling({DeprecationBehavior deprecationBehavior = DeprecationBehavior.none}) async { Future<void> ensureReadyForPlatformSpecificTooling({DeprecationBehavior deprecationBehavior = DeprecationBehavior.none}) async {
......
...@@ -16,7 +16,6 @@ import 'cache.dart'; ...@@ -16,7 +16,6 @@ import 'cache.dart';
import 'convert.dart'; import 'convert.dart';
import 'device.dart'; import 'device.dart';
import 'globals.dart' as globals; import 'globals.dart' as globals;
import 'ios/xcodeproj.dart';
import 'project.dart'; import 'project.dart';
import 'version.dart'; import 'version.dart';
...@@ -41,8 +40,6 @@ const String kFlutterVersionServiceName = 'flutterVersion'; ...@@ -41,8 +40,6 @@ const String kFlutterVersionServiceName = 'flutterVersion';
const String kCompileExpressionServiceName = 'compileExpression'; const String kCompileExpressionServiceName = 'compileExpression';
const String kFlutterMemoryInfoServiceName = 'flutterMemoryInfo'; const String kFlutterMemoryInfoServiceName = 'flutterMemoryInfo';
const String kFlutterGetSkSLServiceName = 'flutterGetSkSL'; const String kFlutterGetSkSLServiceName = 'flutterGetSkSL';
const String kFlutterGetIOSBuildOptionsServiceName = 'flutterGetIOSBuildOptions';
const String kFlutterGetIOSUniversalLinkSettingsServiceName = 'flutterGetIOSUniversalLinkSettings';
/// The error response code from an unrecoverable compilation failure. /// The error response code from an unrecoverable compilation failure.
const int kIsolateReloadBarred = 1005; const int kIsolateReloadBarred = 1005;
...@@ -315,49 +312,6 @@ Future<vm_service.VmService> setUpVmService({ ...@@ -315,49 +312,6 @@ Future<vm_service.VmService> setUpVmService({
registrationRequests.add(vmService.registerService(kFlutterGetSkSLServiceName, kFlutterToolAlias)); 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) { if (printStructuredErrorLogMethod != null) {
vmService.onExtensionEvent.listen(printStructuredErrorLogMethod); vmService.onExtensionEvent.listen(printStructuredErrorLogMethod);
registrationRequests.add(vmService registrationRequests.add(vmService
......
...@@ -7,6 +7,7 @@ import 'base/file_system.dart'; ...@@ -7,6 +7,7 @@ import 'base/file_system.dart';
import 'base/utils.dart'; import 'base/utils.dart';
import 'build_info.dart'; import 'build_info.dart';
import 'bundle.dart' as bundle; import 'bundle.dart' as bundle;
import 'convert.dart';
import 'flutter_plugins.dart'; import 'flutter_plugins.dart';
import 'globals.dart' as globals; import 'globals.dart' as globals;
import 'ios/code_signing.dart'; import 'ios/code_signing.dart';
...@@ -214,7 +215,11 @@ class IosProject extends XcodeBasedProject { ...@@ -214,7 +215,11 @@ class IosProject extends XcodeBasedProject {
return parent.isModule || _editableDirectory.existsSync(); 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 configuration,
required String scheme, required String scheme,
required String target, required String target,
...@@ -224,12 +229,16 @@ class IosProject extends XcodeBasedProject { ...@@ -224,12 +229,16 @@ class IosProject extends XcodeBasedProject {
scheme: scheme, scheme: scheme,
target: target, target: target,
); );
final File file = await parent.buildDirectory
return XcodeUniversalLinkSettings( .childDirectory('deeplink_data')
bundleIdentifier: await _productBundleIdentifierWithBuildContext(context), .childFile('universal-link-settings-$configuration-$scheme-$target.json')
teamIdentifier: await _getTeamIdentifier(context), .create(recursive: true);
associatedDomains: await _getAssociatedDomains(context), 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 /// The product bundle identifier of the host app, or null if not set or if
......
...@@ -751,13 +751,16 @@ apply plugin: 'kotlin-android' ...@@ -751,13 +751,16 @@ apply plugin: 'kotlin-android'
'applinks:example2.com', 'applinks:example2.com',
], ],
); );
final XcodeUniversalLinkSettings settings = await project.ios.universalLinkSettings( final String outputFilePath = await project.ios.outputUniversalLinkSettings(
target: 'Runner', target: 'Runner',
scheme: 'Debug', scheme: 'Debug',
configuration: 'config', configuration: 'config',
); );
final File outputFile = fs.file(outputFilePath);
final Map<String, Object?> json = jsonDecode(outputFile.readAsStringSync()) as Map<String, Object?>;
expect( expect(
settings.associatedDomains, json['associatedDomains'],
unorderedEquals( unorderedEquals(
<String>[ <String>[
'example.com', 'example.com',
...@@ -765,8 +768,8 @@ apply plugin: 'kotlin-android' ...@@ -765,8 +768,8 @@ apply plugin: 'kotlin-android'
], ],
), ),
); );
expect(settings.teamIdentifier, 'ABC'); expect(json['teamIdentifier'], 'ABC');
expect(settings.bundleIdentifier, 'io.flutter.someProject.suffix'); expect(json['bundleIdentifier'], 'io.flutter.someProject.suffix');
}); });
testWithMocks('can handle entitlement file in nested directory structure.', () async { testWithMocks('can handle entitlement file in nested directory structure.', () async {
...@@ -796,13 +799,16 @@ apply plugin: 'kotlin-android' ...@@ -796,13 +799,16 @@ apply plugin: 'kotlin-android'
'applinks:example2.com', 'applinks:example2.com',
], ],
); );
final XcodeUniversalLinkSettings settings = await project.ios.universalLinkSettings(
final String outputFilePath = await project.ios.outputUniversalLinkSettings(
target: 'Runner', target: 'Runner',
scheme: 'Debug', scheme: 'Debug',
configuration: 'config', configuration: 'config',
); );
final File outputFile = fs.file(outputFilePath);
final Map<String, Object?> json = jsonDecode(outputFile.readAsStringSync()) as Map<String, Object?>;
expect( expect(
settings.associatedDomains, json['associatedDomains'],
unorderedEquals( unorderedEquals(
<String>[ <String>[
'example.com', 'example.com',
...@@ -810,8 +816,8 @@ apply plugin: 'kotlin-android' ...@@ -810,8 +816,8 @@ apply plugin: 'kotlin-android'
], ],
), ),
); );
expect(settings.teamIdentifier, 'ABC'); expect(json['teamIdentifier'], 'ABC');
expect(settings.bundleIdentifier, 'io.flutter.someProject.suffix'); expect(json['bundleIdentifier'], 'io.flutter.someProject.suffix');
}); });
testWithMocks('return empty when no entitlement', () async { testWithMocks('return empty when no entitlement', () async {
...@@ -830,13 +836,16 @@ apply plugin: 'kotlin-android' ...@@ -830,13 +836,16 @@ apply plugin: 'kotlin-android'
}; };
xcodeProjectInterpreter.xcodeProjectInfo = XcodeProjectInfo(<String>[], <String>[], <String>['Runner'], logger); xcodeProjectInterpreter.xcodeProjectInfo = XcodeProjectInfo(<String>[], <String>[], <String>['Runner'], logger);
testPlistUtils.setProperty(PlistParser.kCFBundleIdentifierKey, r'$(PRODUCT_BUNDLE_IDENTIFIER)'); testPlistUtils.setProperty(PlistParser.kCFBundleIdentifierKey, r'$(PRODUCT_BUNDLE_IDENTIFIER)');
final XcodeUniversalLinkSettings settings = await project.ios.universalLinkSettings( final String outputFilePath = await project.ios.outputUniversalLinkSettings(
target: 'Runner', target: 'Runner',
scheme: 'Debug', scheme: 'Debug',
configuration: 'config', configuration: 'config',
); );
expect(settings.teamIdentifier, 'ABC'); final File outputFile = fs.file(outputFilePath);
expect(settings.bundleIdentifier, 'io.flutter.someProject'); 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>[]));
}); });
}); });
......
...@@ -74,14 +74,6 @@ const List<VmServiceExpectation> kAttachIsolateExpectations = ...@@ -74,14 +74,6 @@ const List<VmServiceExpectation> kAttachIsolateExpectations =
'service': kFlutterMemoryInfoServiceName, 'service': kFlutterMemoryInfoServiceName,
'alias': kFlutterToolAlias, 'alias': kFlutterToolAlias,
}), }),
FakeVmServiceRequest(method: 'registerService', args: <String, Object>{
'service': kFlutterGetIOSBuildOptionsServiceName,
'alias': kFlutterToolAlias,
}),
FakeVmServiceRequest(method: 'registerService', args: <String, Object>{
'service': kFlutterGetIOSUniversalLinkSettingsServiceName,
'alias': kFlutterToolAlias,
}),
FakeVmServiceRequest( FakeVmServiceRequest(
method: 'streamListen', method: 'streamListen',
args: <String, Object>{ args: <String, Object>{
......
...@@ -9,8 +9,6 @@ import 'package:flutter_tools/src/base/io.dart' as io; ...@@ -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/base/logger.dart';
import 'package:flutter_tools/src/convert.dart'; import 'package:flutter_tools/src/convert.dart';
import 'package:flutter_tools/src/device.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:flutter_tools/src/vmservice.dart';
import 'package:test/fake.dart'; import 'package:test/fake.dart';
import 'package:vm_service/vm_service.dart' as vm_service; import 'package:vm_service/vm_service.dart' as vm_service;
...@@ -85,17 +83,6 @@ void main() { ...@@ -85,17 +83,6 @@ void main() {
expect(mockVMService.services, containsPair(kFlutterMemoryInfoServiceName, kFlutterToolAlias)); 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 { testWithoutContext('VM Service registers flutterGetSkSL service', () async {
final MockVMService mockVMService = MockVMService(); final MockVMService mockVMService = MockVMService();
await setUpVmService( await setUpVmService(
...@@ -277,50 +264,6 @@ void main() { ...@@ -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 { testWithoutContext('runInView forwards arguments correctly', () async {
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost( final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(
requests: <VmServiceExpectation>[ requests: <VmServiceExpectation>[
...@@ -908,26 +851,6 @@ void main() { ...@@ -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 { class MockVMService extends Fake implements vm_service.VmService {
final Map<String, String> services = <String, String>{}; final Map<String, String> services = <String, String>{};
final Map<String, vm_service.ServiceCallback> serviceCallBacks = <String, vm_service.ServiceCallback>{}; final Map<String, vm_service.ServiceCallback> serviceCallBacks = <String, vm_service.ServiceCallback>{};
......
...@@ -59,12 +59,6 @@ void main() { ...@@ -59,12 +59,6 @@ void main() {
expect(response.type, 'Success'); 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 { testWithoutContext('reloadSources can be called', () async {
final VM vm = await vmService.getVM(); final VM vm = await vmService.getVM();
final IsolateRef? isolateRef = vm.isolates?.first; final IsolateRef? isolateRef = vm.isolates?.first;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment