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 {
}
}
/// 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`.
......
......@@ -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 {
......
......@@ -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
......
......@@ -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
......
......@@ -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>[]));
});
});
......
......@@ -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>{
......
......@@ -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>{};
......
......@@ -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;
......
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