[flutter_tools] replace vm_service extension methods with wrapper class (#76721)

This commit is contained in:
Jonah Williams 2021-02-24 15:40:33 -08:00 committed by GitHub
parent a9eb24d64c
commit a3b14c58ae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 185 additions and 225 deletions

View file

@ -132,7 +132,7 @@ class ScreenshotCommand extends FlutterCommand {
Future<bool> runSkia(File outputFile) async {
final Uri observatoryUri = Uri.parse(stringArg(_kObservatoryUri));
final vm_service.VmService vmService = await connectToVmService(observatoryUri);
final FlutterVmService vmService = await connectToVmService(observatoryUri);
final vm_service.Response skp = await vmService.screenshotSkp();
if (skp == null) {
globals.printError(
@ -156,7 +156,7 @@ class ScreenshotCommand extends FlutterCommand {
Future<bool> runRasterizer(File outputFile) async {
final Uri observatoryUri = Uri.parse(stringArg(_kObservatoryUri));
final vm_service.VmService vmService = await connectToVmService(observatoryUri);
final FlutterVmService vmService = await connectToVmService(observatoryUri);
final vm_service.Response response = await vmService.screenshot();
if (response == null) {
globals.printError(

View file

@ -226,7 +226,7 @@ abstract class DevFSWriter {
class _DevFSHttpWriter implements DevFSWriter {
_DevFSHttpWriter(
this.fsName,
vm_service.VmService serviceProtocol, {
FlutterVmService serviceProtocol, {
@required OperatingSystemUtils osUtils,
@required HttpClient httpClient,
@required Logger logger,
@ -372,7 +372,7 @@ class DevFS {
///
/// Failed uploads are retried after [uploadRetryThrottle] duration, defaults to 500ms.
DevFS(
vm_service.VmService serviceProtocol,
FlutterVmService serviceProtocol,
this.fsName,
this.rootDirectory, {
@required OperatingSystemUtils osUtils,
@ -394,7 +394,7 @@ class DevFS {
: context.get<HttpClientFactory>()())
);
final vm_service.VmService _vmService;
final FlutterVmService _vmService;
final _DevFSHttpWriter _httpWriter;
final Logger _logger;
final FileSystem _fileSystem;

View file

@ -9,7 +9,6 @@ import 'dart:math' as math;
import 'package:meta/meta.dart';
import 'package:process/process.dart';
import 'package:vm_service/vm_service.dart' as vm_service;
import 'android/android_device_discovery.dart';
import 'android/android_sdk.dart';
@ -45,6 +44,7 @@ import 'macos/xcode.dart';
import 'project.dart';
import 'tester/flutter_tester.dart';
import 'version.dart';
import 'vmservice.dart';
import 'web/web_device.dart';
import 'windows/windows_device.dart';
import 'windows/windows_workflow.dart';
@ -1031,7 +1031,7 @@ abstract class DeviceLogReader {
/// Some logs can be obtained from a VM service stream.
/// Set this after the VM services are connected.
vm_service.VmService connectedVMService;
FlutterVmService connectedVMService;
@override
String toString() => name;
@ -1061,7 +1061,7 @@ class NoOpDeviceLogReader implements DeviceLogReader {
int appPid;
@override
vm_service.VmService connectedVMService;
FlutterVmService connectedVMService;
@override
Stream<String> get logLines => const Stream<String>.empty();

View file

@ -127,7 +127,7 @@ class FlutterDriverService extends DriverService {
Device _device;
ApplicationPackage _applicationPackage;
String _vmServiceUri;
vm_service.VmService _vmService;
FlutterVmService _vmService;
@override
Future<void> start(
@ -220,7 +220,7 @@ class FlutterDriverService extends DriverService {
final DeviceLogReader logReader = await device.getLogReader(app: _applicationPackage);
logReader.logLines.listen(_logger.printStatus);
final vm_service.VM vm = await _vmService.getVM();
final vm_service.VM vm = await _vmService.service.getVM();
logReader.appPid = vm.pid;
}
@ -268,7 +268,7 @@ class FlutterDriverService extends DriverService {
}
} else if (_device.supportsFlutterExit) {
// Otherwise use the VM Service URI to stop the app as a best effort approach.
final vm_service.VM vm = await _vmService.getVM();
final vm_service.VM vm = await _vmService.service.getVM();
final vm_service.IsolateRef isolateRef = vm.isolates
.firstWhere((vm_service.IsolateRef element) {
return !element.isSystemIsolate;

View file

@ -7,7 +7,6 @@
import 'dart:async';
import 'package:meta/meta.dart';
import 'package:vm_service/vm_service.dart' as vm_service;
import '../application_package.dart';
import '../artifacts.dart';
@ -50,7 +49,7 @@ final String _ipv4Loopback = InternetAddress.loopbackIPv4.address;
final String _ipv6Loopback = InternetAddress.loopbackIPv6.address;
// Enables testing the fuchsia isolate discovery
Future<vm_service.VmService> _kDefaultFuchsiaIsolateDiscoveryConnector(Uri uri) {
Future<FlutterVmService> _kDefaultFuchsiaIsolateDiscoveryConnector(Uri uri) {
return connectToVmService(uri);
}
@ -689,7 +688,7 @@ class FuchsiaDevice extends Device {
// netstat shows that the local port is actually being used on the IPv6
// loopback (::1).
final Uri uri = Uri.parse('http://[$_ipv6Loopback]:$port');
final vm_service.VmService vmService = await connectToVmService(uri);
final FlutterVmService vmService = await connectToVmService(uri);
final List<FlutterView> flutterViews = await vmService.getFlutterViews();
for (final FlutterView flutterView in flutterViews) {
if (flutterView.uiIsolate == null) {
@ -732,11 +731,11 @@ class FuchsiaIsolateDiscoveryProtocol {
]);
static const Duration _pollDuration = Duration(seconds: 10);
final Map<int, vm_service.VmService> _ports = <int, vm_service.VmService>{};
final Map<int, FlutterVmService> _ports = <int, FlutterVmService>{};
final FuchsiaDevice _device;
final String _isolateName;
final Completer<Uri> _foundUri = Completer<Uri>();
final Future<vm_service.VmService> Function(Uri) _vmServiceConnector;
final Future<FlutterVmService> Function(Uri) _vmServiceConnector;
final Future<void> Function(Device, Uri, bool) _ddsStarter;
// whether to only poll once.
final bool _pollOnce;
@ -772,7 +771,7 @@ class FuchsiaIsolateDiscoveryProtocol {
Future<void> _findIsolate() async {
final List<int> ports = await _device.servicePorts();
for (final int port in ports) {
vm_service.VmService service;
FlutterVmService service;
if (_ports.containsKey(port)) {
service = _ports[port];
} else {

View file

@ -656,29 +656,29 @@ class IOSDeviceLogReader extends DeviceLogReader {
Stream<String> get logLines => _linesController.stream;
@override
vm_service.VmService get connectedVMService => _connectedVMService;
vm_service.VmService _connectedVMService;
FlutterVmService get connectedVMService => _connectedVMService;
FlutterVmService _connectedVMService;
@override
set connectedVMService(vm_service.VmService connectedVmService) {
set connectedVMService(FlutterVmService connectedVmService) {
_listenToUnifiedLoggingEvents(connectedVmService);
_connectedVMService = connectedVmService;
}
static const int minimumUniversalLoggingSdkVersion = 13;
Future<void> _listenToUnifiedLoggingEvents(vm_service.VmService connectedVmService) async {
Future<void> _listenToUnifiedLoggingEvents(FlutterVmService connectedVmService) async {
if (_majorSdkVersion < minimumUniversalLoggingSdkVersion) {
return;
}
try {
// The VM service will not publish logging events unless the debug stream is being listened to.
// Listen to this stream as a side effect.
unawaited(connectedVmService.streamListen('Debug'));
unawaited(connectedVmService.service.streamListen('Debug'));
await Future.wait(<Future<void>>[
connectedVmService.streamListen(vm_service.EventStreams.kStdout),
connectedVmService.streamListen(vm_service.EventStreams.kStderr),
connectedVmService.service.streamListen(vm_service.EventStreams.kStdout),
connectedVmService.service.streamListen(vm_service.EventStreams.kStderr),
]);
} on vm_service.RPCError {
// Do nothing, since the tool is already subscribed.
@ -696,8 +696,8 @@ class IOSDeviceLogReader extends DeviceLogReader {
}
_loggingSubscriptions.addAll(<StreamSubscription<void>>[
connectedVmService.onStdoutEvent.listen(logMessage),
connectedVmService.onStderrEvent.listen(logMessage),
connectedVmService.service.onStdoutEvent.listen(logMessage),
connectedVmService.service.onStderrEvent.listen(logMessage),
]);
}

View file

@ -122,8 +122,16 @@ abstract class ResidentWebRunner extends ResidentRunner {
WipConnection _wipConnection;
ChromiumLauncher _chromiumLauncher;
vmservice.VmService get _vmService =>
_connectionResult?.debugConnection?.vmService;
FlutterVmService get _vmService {
if (_instance != null) {
return _instance;
}
final vmservice.VmService service =_connectionResult?.debugConnection?.vmService;
final Uri websocketUri = Uri.parse(_connectionResult.debugConnection.uri);
final Uri httpUri = _httpUriFromWebsocketUri(websocketUri);
return _instance ??= FlutterVmService(service, wsAddress: websocketUri, httpAddress: httpUri);
}
FlutterVmService _instance;
@override
bool get canHotRestart {
@ -137,7 +145,7 @@ abstract class ResidentWebRunner extends ResidentRunner {
Map<String, dynamic> params,
}) async {
final vmservice.Response response =
await _vmService.callServiceExtension(method, args: params);
await _vmService.service.callServiceExtension(method, args: params);
return response.toJson();
}
@ -598,7 +606,7 @@ class _ResidentWebRunner extends ResidentWebRunner {
if (!deviceIsDebuggable) {
globals.printStatus('Recompile complete. Page requires refresh.');
} else if (isRunningDebug) {
await _vmService.callMethod('hotRestart');
await _vmService.service.callMethod('hotRestart');
} else {
// On non-debug builds, a hard refresh is required to ensure the
// up to date sources are loaded.
@ -771,36 +779,36 @@ class _ResidentWebRunner extends ResidentWebRunner {
globals.printStatus(message);
}
_stdOutSub = _vmService.onStdoutEvent.listen(onLogEvent);
_stdErrSub = _vmService.onStderrEvent.listen(onLogEvent);
_stdOutSub = _vmService.service.onStdoutEvent.listen(onLogEvent);
_stdErrSub = _vmService.service.onStderrEvent.listen(onLogEvent);
_extensionEventSub =
_vmService.onExtensionEvent.listen(printStructuredErrorLog);
_vmService.service.onExtensionEvent.listen(printStructuredErrorLog);
try {
await _vmService.streamListen(vmservice.EventStreams.kStdout);
await _vmService.service.streamListen(vmservice.EventStreams.kStdout);
} on vmservice.RPCError {
// It is safe to ignore this error because we expect an error to be
// thrown if we're not already subscribed.
}
try {
await _vmService.streamListen(vmservice.EventStreams.kStderr);
await _vmService.service.streamListen(vmservice.EventStreams.kStderr);
} on vmservice.RPCError {
// It is safe to ignore this error because we expect an error to be
// thrown if we're not already subscribed.
}
try {
await _vmService.streamListen(vmservice.EventStreams.kIsolate);
await _vmService.service.streamListen(vmservice.EventStreams.kIsolate);
} on vmservice.RPCError {
// It is safe to ignore this error because we expect an error to be
// thrown if we're not already subscribed.
}
try {
await _vmService.streamListen(vmservice.EventStreams.kExtension);
await _vmService.service.streamListen(vmservice.EventStreams.kExtension);
} on vmservice.RPCError {
// It is safe to ignore this error because we expect an error to be
// thrown if we're not already subscribed.
}
unawaited(_vmService.registerService('reloadSources', 'FlutterTools'));
_vmService.registerServiceCallback('reloadSources', (Map<String, Object> params) async {
unawaited(_vmService.service.registerService('reloadSources', 'FlutterTools'));
_vmService.service.registerServiceCallback('reloadSources', (Map<String, Object> params) async {
final bool pause = params['pause'] as bool ?? false;
await restart(benchmarkMode: false, pause: pause, fullRestart: false);
return <String, Object>{'type': 'Success'};
@ -808,9 +816,6 @@ class _ResidentWebRunner extends ResidentWebRunner {
websocketUri = Uri.parse(_connectionResult.debugConnection.uri);
device.vmService = _vmService;
// Update caches to enable the FlutterVmService extensions.
setHttpAddress(_httpUriFromWebsocketUri(websocketUri), device.vmService);
setWsAddress(websocketUri, device.vmService);
// Run main immediately if the app is not started paused or if there
// is no debugger attached. Otherwise, runMain when a resume event
@ -865,10 +870,10 @@ class _ResidentWebRunner extends ResidentWebRunner {
await device.exitApps();
appFinished();
}
Uri _httpUriFromWebsocketUri(Uri websocketUri) {
const String wsPath = '/ws';
final String path = websocketUri.path;
return websocketUri.replace(scheme: 'http', path: path.substring(0, path.length - wsPath.length));
}
}
Uri _httpUriFromWebsocketUri(Uri websocketUri) {
const String wsPath = '/ws';
final String path = websocketUri.path;
return websocketUri.replace(scheme: 'http', path: path.substring(0, path.length - wsPath.length));
}

View file

@ -111,7 +111,7 @@ class FlutterResidentDevtoolsHandler implements ResidentDevtoolsHandler {
await Future.wait(<Future<void>>[
for (final FlutterDevice device in flutterDevices)
if (device.vmService != null)
waitForExtension(device.vmService, 'ext.flutter.connectedVmServiceUri'),
waitForExtension(device.vmService.service, 'ext.flutter.connectedVmServiceUri'),
]);
}

View file

@ -195,7 +195,7 @@ class FlutterDevice {
DevFSWriter devFSWriter;
Stream<Uri> observatoryUris;
vm_service.VmService vmService;
FlutterVmService vmService;
DevFS devFS;
ApplicationPackage package;
List<String> fileSystemRoots;
@ -237,7 +237,7 @@ class FlutterDevice {
globals.printTrace('Connecting to service protocol: $observatoryUri');
isWaitingForVm = true;
bool existingDds = false;
vm_service.VmService service;
FlutterVmService service;
if (!disableDds) {
void handleError(Exception e, StackTrace st) {
globals.printTrace('Fail to connect to service protocol: $observatoryUri: $e');
@ -250,9 +250,6 @@ class FlutterDevice {
// from an old application instance, we shouldn't try and start DDS.
try {
service = await connectToVmService(observatoryUri);
// TODO(dnfield): Remove ignore once internal repo is up to date
// https://github.com/flutter/flutter/issues/74518
// ignore: await_only_futures
await service.dispose();
} on Exception catch (exception) {
globals.printTrace('Fail to connect to service protocol: $observatoryUri: $exception');
@ -306,7 +303,7 @@ class FlutterDevice {
if (!existingDds)
device.dds.done.whenComplete(() => throw Exception('DDS shut down too early')),
]
) as vm_service.VmService;
) as FlutterVmService;
} on Exception catch (exception) {
globals.printTrace('Fail to connect to service protocol: $observatoryUri: $exception');
if (!completer.isCompleted && !_isListeningForObservatoryUri) {
@ -365,7 +362,7 @@ class FlutterDevice {
));
}
}
return vmService.onDone
return vmService.service.onDone
.catchError((dynamic error, StackTrace stackTrace) {
globals.logger.printError(
'unhandled error waiting for vm service exit:\n $error',
@ -556,7 +553,7 @@ class FlutterDevice {
}
Future<void> initLogReader() async {
final vm_service.VM vm = await vmService.getVM();
final vm_service.VM vm = await vmService.service.getVM();
final DeviceLogReader logReader = await device.getLogReader(app: package);
logReader.appPid = vm.pid;
}
@ -1275,7 +1272,7 @@ abstract class ResidentRunner {
// This hooks up callbacks for when the connection stops in the future.
// We don't want to wait for them. We don't handle errors in those callbacks'
// futures either because they just print to logger and is not critical.
unawaited(device.vmService.onDone.then<void>(
unawaited(device.vmService.service.onDone.then<void>(
_serviceProtocolDone,
onError: _serviceProtocolError,
).whenComplete(_serviceDisconnected));
@ -1682,8 +1679,6 @@ class TerminalHandler {
class DebugConnectionInfo {
DebugConnectionInfo({ this.httpUri, this.wsUri, this.baseUri });
// TODO(danrubel): the httpUri field should be removed as part of
// https://github.com/flutter/flutter/issues/7050
final Uri httpUri;
final Uri wsUri;
final String baseUri;

View file

@ -278,7 +278,7 @@ class HotRunner extends ResidentRunner {
// Measure time to perform a hot restart.
globals.printStatus('Benchmarking hot restart');
await restart(fullRestart: true);
// Wait multiple seconds to stabilize benchmark on slower devicelab hardware.
// Wait multiple seconds to stabilize benchmark on slower device lab hardware.
// Hot restart finishes when the new isolate is started, not when the new isolate
// is ready. This process can actually take multiple seconds.
await Future<void>.delayed(const Duration(seconds: 10));
@ -532,17 +532,17 @@ class HotRunner extends ResidentRunner {
// The embedder requires that the isolate is unpaused, because the
// runInView method requires interaction with dart engine APIs that
// are not thread-safe, and thus must be run on the same thread that
// would be blocked by the pause. Simply unpausing is not sufficient,
// would be blocked by the pause. Simply un-pausing is not sufficient,
// because this does not prevent the isolate from immediately hitting
// a breakpoint, for example if the breakpoint was placed in a loop
// or in a frequently called method. Instead, all breakpoints are first
// disabled and then the isolate resumed.
final List<Future<void>> breakpointRemoval = <Future<void>>[
for (final vm_service.Breakpoint breakpoint in isolate.breakpoints)
device.vmService.removeBreakpoint(isolate.id, breakpoint.id)
device.vmService.service.removeBreakpoint(isolate.id, breakpoint.id)
];
await Future.wait(breakpointRemoval);
await device.vmService.resume(view.uiIsolate.id);
await device.vmService.service.resume(view.uiIsolate.id);
}
}));
}
@ -550,12 +550,12 @@ class HotRunner extends ResidentRunner {
// The engine handles killing and recreating isolates that it has spawned
// ("uiIsolates"). The isolates that were spawned from these uiIsolates
// will not be restarted, and so they must be manually killed.
final vm_service.VM vm = await device.vmService.getVM();
final vm_service.VM vm = await device.vmService.service.getVM();
for (final vm_service.IsolateRef isolateRef in vm.isolates) {
if (uiIsolatesIds.contains(isolateRef.id)) {
continue;
}
operations.add(device.vmService.kill(isolateRef.id)
operations.add(device.vmService.service.kill(isolateRef.id)
.catchError((dynamic error, StackTrace stackTrace) {
// Do nothing on a SentinelException since it means the isolate
// has already been killed.
@ -788,10 +788,10 @@ class HotRunner extends ResidentRunner {
}) async {
final String deviceEntryUri = device.devFS.baseUri
.resolve(entryPath).toString();
final vm_service.VM vm = await device.vmService.getVM();
final vm_service.VM vm = await device.vmService.service.getVM();
return <Future<vm_service.ReloadReport>>[
for (final vm_service.IsolateRef isolateRef in vm.isolates)
device.vmService.reloadSources(
device.vmService.service.reloadSources(
isolateRef.id,
pause: pause,
rootLibUri: deviceEntryUri,
@ -850,7 +850,7 @@ class HotRunner extends ResidentRunner {
await _evictDirtyAssets();
// Check if any isolates are paused and reassemble those that aren't.
final Map<FlutterView, vm_service.VmService> reassembleViews = <FlutterView, vm_service.VmService>{};
final Map<FlutterView, FlutterVmService> reassembleViews = <FlutterView, FlutterVmService>{};
final List<Future<void>> reassembleFutures = <Future<void>>[];
String serviceEventKind;
int pausedIsolatesFound = 0;

View file

@ -202,7 +202,7 @@ class CoverageCollector extends TestWatcher {
Future<void> handleTestTimedOut(TestDevice testDevice) async { }
}
Future<vm_service.VmService> _defaultConnect(Uri serviceUri) {
Future<FlutterVmService> _defaultConnect(Uri serviceUri) {
return connectToVmService(
serviceUri, compression: CompressionOptions.compressionOff);
}
@ -210,14 +210,10 @@ Future<vm_service.VmService> _defaultConnect(Uri serviceUri) {
Future<Map<String, dynamic>> collect(Uri serviceUri, bool Function(String) libraryPredicate, {
bool waitPaused = false,
String debugName,
Future<vm_service.VmService> Function(Uri) connector = _defaultConnect,
Future<FlutterVmService> Function(Uri) connector = _defaultConnect,
}) async {
final vm_service.VmService vmService = await connector(serviceUri);
final Map<String, dynamic> result = await _getAllCoverage(
vmService, libraryPredicate);
// TODO(dnfield): Remove ignore once internal repo is up to date
// https://github.com/flutter/flutter/issues/74518
// ignore: await_only_futures
final FlutterVmService vmService = await connector(serviceUri);
final Map<String, dynamic> result = await _getAllCoverage(vmService.service, libraryPredicate);
await vmService.dispose();
return result;
}

View file

@ -11,7 +11,6 @@ import 'package:dds/dds.dart';
import 'package:meta/meta.dart';
import 'package:process/process.dart';
import 'package:stream_channel/stream_channel.dart';
import 'package:vm_service/vm_service.dart' as vm_service;
import '../base/common.dart';
import '../base/file_system.dart';
@ -165,11 +164,11 @@ class FlutterTesterTestDevice extends TestDevice {
}
logger.printTrace('Connecting to service protocol: $forwardingUri');
final Future<vm_service.VmService> localVmService = connectToVmService(
final Future<FlutterVmService> localVmService = connectToVmService(
forwardingUri,
compileExpression: compileExpression,
);
unawaited(localVmService.then((vm_service.VmService vmservice) {
unawaited(localVmService.then((FlutterVmService vmservice) {
logger.printTrace('test $id: Successfully connected to service protocol: $forwardingUri');
}));

View file

@ -30,12 +30,12 @@ class Tracing {
static const String firstUsefulFrameEventName = kFirstFrameRasterizedEventName;
final vm_service.VmService vmService;
final FlutterVmService vmService;
final Logger _logger;
Future<void> startTracing() async {
await vmService.setTimelineFlags(<String>['Compiler', 'Dart', 'Embedder', 'GC']);
await vmService.clearVMTimeline();
await vmService.service.clearVMTimeline();
}
/// Stops tracing; optionally wait for first frame.
@ -49,12 +49,12 @@ class Tracing {
try {
final Completer<void> whenFirstFrameRendered = Completer<void>();
try {
await vmService.streamListen(vm_service.EventStreams.kExtension);
await vmService.service.streamListen(vm_service.EventStreams.kExtension);
} on vm_service.RPCError {
// It is safe to ignore this error because we expect an error to be
// thrown if we're already subscribed.
}
vmService.onExtensionEvent.listen((vm_service.Event event) {
vmService.service.onExtensionEvent.listen((vm_service.Event event) {
if (event.extensionKind == 'Flutter.FirstFrame') {
whenFirstFrameRendered.complete();
}
@ -93,7 +93,7 @@ class Tracing {
/// Download the startup trace information from the given observatory client and
/// store it to build/start_up_info.json.
Future<void> downloadStartupTrace(vm_service.VmService vmService, {
Future<void> downloadStartupTrace(FlutterVmService vmService, {
bool awaitFirstFrame = true,
@required Logger logger,
@required Directory output,

View file

@ -146,7 +146,7 @@ Future<io.WebSocket> _defaultOpenChannel(String url, {
/// Override `VMServiceConnector` in [context] to return a different VMService
/// from [VMService.connect] (used by tests).
typedef VMServiceConnector = Future<vm_service.VmService> Function(Uri httpUri, {
typedef VMServiceConnector = Future<FlutterVmService> Function(Uri httpUri, {
ReloadSources reloadSources,
Restart restart,
CompileExpression compileExpression,
@ -156,24 +156,6 @@ typedef VMServiceConnector = Future<vm_service.VmService> Function(Uri httpUri,
Device device,
});
final Expando<Uri> _httpAddressExpando = Expando<Uri>();
final Expando<Uri> _wsAddressExpando = Expando<Uri>();
void setHttpAddress(Uri uri, vm_service.VmService vmService) {
if(vmService == null) {
return;
}
_httpAddressExpando[vmService] = uri;
}
void setWsAddress(Uri uri, vm_service.VmService vmService) {
if(vmService == null) {
return;
}
_wsAddressExpando[vmService] = uri;
}
/// A connection to the Dart VM Service.
vm_service.VmService setUpVmService(
ReloadSources reloadSources,
@ -292,7 +274,7 @@ vm_service.VmService setUpVmService(
/// protocol itself.
///
/// See: https://github.com/dart-lang/sdk/commit/df8bf384eb815cf38450cb50a0f4b62230fba217
Future<vm_service.VmService> connectToVmService(
Future<FlutterVmService> connectToVmService(
Uri httpUri, {
ReloadSources reloadSources,
Restart restart,
@ -314,7 +296,7 @@ Future<vm_service.VmService> connectToVmService(
);
}
Future<vm_service.VmService> _connect(
Future<FlutterVmService> _connect(
Uri httpUri, {
ReloadSources reloadSources,
Restart restart,
@ -344,13 +326,11 @@ Future<vm_service.VmService> _connect(
printStructuredErrorLogMethod,
delegateService,
);
_httpAddressExpando[service] = httpUri;
_wsAddressExpando[service] = wsUri;
// This call is to ensure we are able to establish a connection instead of
// keeping on trucking and failing farther down the process.
await delegateService.getVersion();
return service;
return FlutterVmService(service, httpAddress: httpUri, wsAddress: wsUri);
}
String _validateRpcStringParam(String methodName, Map<String, dynamic> params, String paramName) {
@ -414,10 +394,12 @@ class FlutterView {
}
/// Flutter specific VM Service functionality.
extension FlutterVmService on vm_service.VmService {
Uri get wsAddress => this != null ? _wsAddressExpando[this] : null;
class FlutterVmService {
FlutterVmService(this.service, {this.wsAddress, this.httpAddress});
Uri get httpAddress => this != null ? _httpAddressExpando[this] : null;
final vm_service.VmService service;
final Uri wsAddress;
final Uri httpAddress;
Future<vm_service.Response> callMethodWrapper(
String method, {
@ -425,7 +407,7 @@ extension FlutterVmService on vm_service.VmService {
Map<String, dynamic> args
}) async {
try {
return await callMethod(method, isolateId: isolateId, args: args);
return await service.callMethod(method, isolateId: isolateId, args: args);
} on vm_service.RPCError catch (e) {
// If the service disappears mid-request the tool is unable to recover
// and should begin to shutdown due to the service connection closing.
@ -497,11 +479,11 @@ extension FlutterVmService on vm_service.VmService {
@required Uri assetsDirectory,
}) async {
try {
await streamListen('Isolate');
await service.streamListen('Isolate');
} on vm_service.RPCError {
// Do nothing, since the tool is already subscribed.
}
final Future<void> onRunnable = onIsolateEvent.firstWhere((vm_service.Event event) {
final Future<void> onRunnable = service.onIsolateEvent.firstWhere((vm_service.Event event) {
return event.kind == vm_service.EventKind.kIsolateRunnable;
});
await callMethodWrapper(
@ -741,7 +723,7 @@ extension FlutterVmService on vm_service.VmService {
Map<String, dynamic> args,
}) async {
try {
return await callServiceExtension(method, args: args);
return await service.callServiceExtension(method, args: args);
} on vm_service.RPCError catch (err) {
// If an application is not using the framework or the VM service
// disappears while handling a request, return null.
@ -805,7 +787,7 @@ extension FlutterVmService on vm_service.VmService {
/// Attempt to retrieve the isolate with id [isolateId], or `null` if it has
/// been collected.
Future<vm_service.Isolate> getIsolateOrNull(String isolateId) {
return getIsolate(isolateId)
return service.getIsolate(isolateId)
.catchError((dynamic error, StackTrace stackTrace) {
return null;
}, test: (dynamic error) {
@ -818,7 +800,7 @@ extension FlutterVmService on vm_service.VmService {
Future<vm_service.Response> createDevFS(String fsName) {
// Call the unchecked version of `callServiceExtension` because the caller
// has custom handling of certain RPCErrors.
return callServiceExtension(
return service.callServiceExtension(
'_createDevFS',
args: <String, dynamic>{'fsName': fsName},
);
@ -854,6 +836,13 @@ extension FlutterVmService on vm_service.VmService {
Future<vm_service.Response> getTimeline() {
return _checkedCallServiceExtension('getVMTimeline');
}
Future<void> dispose() async {
// TODO(dnfield): Remove ignore once internal repo is up to date
// https://github.com/flutter/flutter/issues/74518
// ignore: await_only_futures
await service.dispose();
}
}
/// Whether the event attached to an [Isolate.pauseEvent] should be considered

View file

@ -115,8 +115,8 @@ void main() {
final OperatingSystemUtils osUtils = MockOperatingSystemUtils();
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(
requests: <VmServiceExpectation>[failingCreateDevFSRequest],
httpAddress: Uri.parse('http://localhost'),
);
setHttpAddress(Uri.parse('http://localhost'), fakeVmServiceHost.vmService);
final DevFS devFS = DevFS(
fakeVmServiceHost.vmService,
@ -138,9 +138,8 @@ void main() {
createDevFSRequest,
failingDeleteDevFSRequest,
],
httpAddress: Uri.parse('http://localhost'),
);
setHttpAddress(Uri.parse('http://localhost'), fakeVmServiceHost.vmService);
final DevFS devFS = DevFS(
fakeVmServiceHost.vmService,
@ -162,8 +161,8 @@ void main() {
final MockResidentCompiler residentCompiler = MockResidentCompiler();
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(
requests: <VmServiceExpectation>[createDevFSRequest],
httpAddress: Uri.parse('http://localhost'),
);
setHttpAddress(Uri.parse('http://localhost'), fakeVmServiceHost.vmService);
when(residentCompiler.recompile(
any,
@ -215,8 +214,9 @@ void main() {
final FileSystem fileSystem = MemoryFileSystem.test();
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(
requests: <VmServiceExpectation>[createDevFSRequest],
httpAddress: Uri.parse('http://localhost'),
);
setHttpAddress(Uri.parse('http://localhost'), fakeVmServiceHost.vmService);
final DevFS devFS = DevFS(
fakeVmServiceHost.vmService,
'test',
@ -258,8 +258,8 @@ void main() {
final FileSystem fileSystem = MemoryFileSystem.test();
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(
requests: <VmServiceExpectation>[createDevFSRequest],
httpAddress: Uri.parse('http://localhost'),
);
setHttpAddress(Uri.parse('http://localhost'), fakeVmServiceHost.vmService);
final DevFS devFS = DevFS(
fakeVmServiceHost.vmService,

View file

@ -363,7 +363,7 @@ void main() {
FlutterDriverService setUpDriverService({
Logger logger,
ProcessManager processManager,
vm_service.VmService vmService,
FlutterVmService vmService,
}) {
logger ??= BufferLogger.test();
return FlutterDriverService(

View file

@ -747,6 +747,7 @@ void main() {
},
),
],
httpAddress: Uri.parse('example'),
);
final MockFuchsiaDevice fuchsiaDevice =
MockFuchsiaDevice('123', portForwarder, false);
@ -766,7 +767,6 @@ void main() {
.thenAnswer((Invocation invocation) async => <int>[1]);
when(portForwarder.forward(1))
.thenAnswer((Invocation invocation) async => 2);
setHttpAddress(Uri.parse('example'), fakeVmServiceHost.vmService);
return await discoveryProtocol.uri;
}

View file

@ -14,6 +14,7 @@ import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/ios/devices.dart';
import 'package:flutter_tools/src/ios/ios_deploy.dart';
import 'package:flutter_tools/src/ios/mac.dart';
import 'package:flutter_tools/src/vmservice.dart';
import 'package:mockito/mockito.dart';
import 'package:vm_service/vm_service.dart';
@ -149,7 +150,29 @@ Runner(libsystem_asl.dylib)[297] <Notice>: libMobileGestalt
group('VM service', () {
testWithoutContext('IOSDeviceLogReader can listen to VM Service logs', () async {
final MockVmService vmService = MockVmService();
final Event stdoutEvent = Event(
kind: 'Stdout',
timestamp: 0,
bytes: base64.encode(utf8.encode(' This is a message ')),
);
final Event stderrEvent = Event(
kind: 'Stderr',
timestamp: 0,
bytes: base64.encode(utf8.encode(' And this is an error ')),
);
final FlutterVmService vmService = FakeVmServiceHost(requests: <VmServiceExpectation>[
const FakeVmServiceRequest(method: 'streamListen', args: <String, Object>{
'streamId': 'Debug',
}),
const FakeVmServiceRequest(method: 'streamListen', args: <String, Object>{
'streamId': 'Stdout',
}),
const FakeVmServiceRequest(method: 'streamListen', args: <String, Object>{
'streamId': 'Stderr',
}),
FakeVmServiceStreamResponse(event: stdoutEvent, streamId: 'Stdout'),
FakeVmServiceStreamResponse(event: stderrEvent, streamId: 'Stderr'),
]).vmService;
final DeviceLogReader logReader = IOSDeviceLogReader.test(
useSyslog: false,
iMobileDevice: IMobileDevice(
@ -159,47 +182,39 @@ Runner(libsystem_asl.dylib)[297] <Notice>: libMobileGestalt
logger: logger,
),
);
final StreamController<Event> stdoutController = StreamController<Event>();
final StreamController<Event> stderController = StreamController<Event>();
final Completer<Success> stdoutCompleter = Completer<Success>();
final Completer<Success> stderrCompleter = Completer<Success>();
when(vmService.streamListen('Stdout')).thenAnswer((Invocation invocation) {
return stdoutCompleter.future;
});
when(vmService.streamListen('Stderr')).thenAnswer((Invocation invocation) {
return stderrCompleter.future;
});
when(vmService.onStdoutEvent).thenAnswer((Invocation invocation) {
return stdoutController.stream;
});
when(vmService.onStderrEvent).thenAnswer((Invocation invocation) {
return stderController.stream;
});
logReader.connectedVMService = vmService;
stdoutCompleter.complete(Success());
stderrCompleter.complete(Success());
stdoutController.add(Event(
kind: 'Stdout',
timestamp: 0,
bytes: base64.encode(utf8.encode(' This is a message ')),
));
stderController.add(Event(
kind: 'Stderr',
timestamp: 0,
bytes: base64.encode(utf8.encode(' And this is an error ')),
));
// Wait for stream listeners to fire.
await expectLater(logReader.logLines, emitsInAnyOrder(<Matcher>[
equals(' This is a message '),
equals(' And this is an error '),
]));
verify(vmService.streamListen('Debug'));
});
testWithoutContext('IOSDeviceLogReader ignores VM Service logs when attached to debugger', () async {
final MockVmService vmService = MockVmService();
final Event stdoutEvent = Event(
kind: 'Stdout',
timestamp: 0,
bytes: base64.encode(utf8.encode(' This is a message ')),
);
final Event stderrEvent = Event(
kind: 'Stderr',
timestamp: 0,
bytes: base64.encode(utf8.encode(' And this is an error ')),
);
final FlutterVmService vmService = FakeVmServiceHost(requests: <VmServiceExpectation>[
const FakeVmServiceRequest(method: 'streamListen', args: <String, Object>{
'streamId': 'Debug',
}),
const FakeVmServiceRequest(method: 'streamListen', args: <String, Object>{
'streamId': 'Stdout',
}),
const FakeVmServiceRequest(method: 'streamListen', args: <String, Object>{
'streamId': 'Stderr',
}),
FakeVmServiceStreamResponse(event: stdoutEvent, streamId: 'Stdout'),
FakeVmServiceStreamResponse(event: stderrEvent, streamId: 'Stderr'),
]).vmService;
final IOSDeviceLogReader logReader = IOSDeviceLogReader.test(
useSyslog: false,
iMobileDevice: IMobileDevice(
@ -209,37 +224,8 @@ Runner(libsystem_asl.dylib)[297] <Notice>: libMobileGestalt
logger: logger,
),
);
final StreamController<Event> stdoutController = StreamController<Event>();
final StreamController<Event> stderController = StreamController<Event>();
final Completer<Success> stdoutCompleter = Completer<Success>();
final Completer<Success> stderrCompleter = Completer<Success>();
when(vmService.streamListen('Stdout')).thenAnswer((Invocation invocation) {
return stdoutCompleter.future;
});
when(vmService.streamListen('Stderr')).thenAnswer((Invocation invocation) {
return stderrCompleter.future;
});
when(vmService.onStdoutEvent).thenAnswer((Invocation invocation) {
return stdoutController.stream;
});
when(vmService.onStderrEvent).thenAnswer((Invocation invocation) {
return stderController.stream;
});
logReader.connectedVMService = vmService;
stdoutCompleter.complete(Success());
stderrCompleter.complete(Success());
stdoutController.add(Event(
kind: 'Stdout',
timestamp: 0,
bytes: base64.encode(utf8.encode(' This is a message ')),
));
stderController.add(Event(
kind: 'Stderr',
timestamp: 0,
bytes: base64.encode(utf8.encode(' And this is an error ')),
));
final MockIOSDeployDebugger iosDeployDebugger = MockIOSDeployDebugger();
when(iosDeployDebugger.debuggerAttached).thenReturn(true);
@ -327,5 +313,4 @@ Runner(libsystem_asl.dylib)[297] <Notice>: libMobileGestalt
});
}
class MockVmService extends Mock implements VmService {}
class MockIOSDeployDebugger extends Mock implements IOSDeployDebugger {}

View file

@ -208,11 +208,10 @@ void main() {
'value': 'http://localhost:1234',
},
),
]);
], httpAddress: Uri.parse('http://localhost:1234'));
final FakeFlutterDevice device = FakeFlutterDevice()
..vmService = fakeVmServiceHost.vmService;
setHttpAddress(Uri.parse('http://localhost:1234'), fakeVmServiceHost.vmService);
await handler.serveAndAnnounceDevTools(
flutterDevices: <FlutterDevice>[device],
@ -236,7 +235,7 @@ void main() {
},
),
]);
waitForExtension(fakeVmServiceHost.vmService, 'foo');
waitForExtension(fakeVmServiceHost.vmService.service, 'foo');
});
testWithoutContext('wait for extension handles no isolates', () {
@ -270,7 +269,7 @@ void main() {
),
),
]);
waitForExtension(fakeVmServiceHost.vmService, 'foo');
waitForExtension(fakeVmServiceHost.vmService.service, 'foo');
});
}
@ -298,5 +297,5 @@ class FakeResidentRunner extends Fake implements ResidentRunner {
class FakeFlutterDevice extends Fake implements FlutterDevice {
@override
vm_service.VmService vmService;
FlutterVmService vmService;
}

View file

@ -2246,8 +2246,7 @@ void main() {
listViews,
listViews,
setAssetBundlePath,
]);
setWsAddress(testUri, fakeVmServiceHost.vmService);
], wsAddress: testUri);
globals.fs.file(globals.fs.path.join('lib', 'main.dart')).createSync(recursive: true);
residentRunner = HotRunner(
<FlutterDevice>[
@ -2277,8 +2276,7 @@ void main() {
listViews,
listViews,
setAssetBundlePath,
]);
setWsAddress(testUri, fakeVmServiceHost.vmService);
], wsAddress: testUri);
globals.fs.file(globals.fs.path.join('lib', 'main.dart')).createSync(recursive: true);
residentRunner = HotRunner(
<FlutterDevice>[
@ -2308,8 +2306,7 @@ void main() {
listViews,
listViews,
setAssetBundlePath,
]);
setWsAddress(testUri, fakeVmServiceHost.vmService);
], wsAddress: testUri);
globals.fs.file(globals.fs.path.join('lib', 'main.dart')).createSync(recursive: true);
residentRunner = HotRunner(
<FlutterDevice>[
@ -2347,8 +2344,7 @@ void main() {
listViews,
listViews,
setAssetBundlePath,
]);
setWsAddress(testUri, fakeVmServiceHost.vmService);
], wsAddress: testUri);
globals.fs.file(globals.fs.path.join('lib', 'main.dart')).createSync(recursive: true);
residentRunner = HotRunner(
<FlutterDevice>[
@ -2386,8 +2382,7 @@ void main() {
listViews,
listViews,
setAssetBundlePath,
]);
setWsAddress(testUri, fakeVmServiceHost.vmService);
], wsAddress: testUri);
globals.fs.file(globals.fs.path.join('lib', 'main.dart')).createSync(recursive: true);
residentRunner = HotRunner(
<FlutterDevice>[
@ -2418,8 +2413,7 @@ void main() {
listViews,
listViews,
setAssetBundlePath,
]);
setWsAddress(testUri, fakeVmServiceHost.vmService);
], wsAddress: testUri);
globals.fs.file(globals.fs.path.join('lib', 'main.dart')).createSync(recursive: true);
residentRunner = HotRunner(
<FlutterDevice>[
@ -2454,7 +2448,7 @@ void main() {
listViews,
listViews,
setAssetBundlePath,
]);
], wsAddress: testUri);
globals.fs.file(globals.fs.path.join('lib', 'main.dart')).createSync(recursive: true);
residentRunner = HotRunner(
<FlutterDevice>[
@ -2514,9 +2508,8 @@ void main() {
testUsingContext('ColdRunner writes vm service file when providing debugging option', () => testbed.run(() async {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
listViews,
]);
], wsAddress: testUri);
globals.fs.file(globals.fs.path.join('lib', 'main.dart')).createSync(recursive: true);
setWsAddress(testUri, fakeVmServiceHost.vmService);
residentRunner = ColdRunner(
<FlutterDevice>[
mockFlutterDevice,
@ -2804,7 +2797,7 @@ void main() {
class MockFlutterDevice extends Mock implements FlutterDevice {}
class MockDartDevelopmentService extends Mock implements DartDevelopmentService {}
class MockVMService extends Mock implements vm_service.VmService {}
class MockVMService extends Mock implements FlutterVmService {}
class MockDevFS extends Mock implements DevFS {}
class MockDeviceLogReader extends Mock implements DeviceLogReader {}
class MockDevtoolsLauncher extends Mock implements DevtoolsLauncher {}

View file

@ -143,7 +143,7 @@ void main() {
return UpdateFSReport(success: true, syncedBytes: 0);
});
when(mockDebugConnection.vmService).thenAnswer((Invocation invocation) {
return fakeVmServiceHost.vmService;
return fakeVmServiceHost.vmService.service;
});
when(mockDebugConnection.onDone).thenAnswer((Invocation invocation) {
return Completer<void>().future;

View file

@ -224,8 +224,9 @@ void main() {
const Stream<String>.empty(),
completer.complete,
);
final FlutterVmService flutterVmService = FlutterVmService(vmService);
unawaited(vmService.setAssetDirectory(
unawaited(flutterVmService.setAssetDirectory(
assetsDirectory: Uri(path: 'abc', scheme: 'file'),
viewId: 'abc',
uiIsolateId: 'def',
@ -249,8 +250,9 @@ void main() {
const Stream<String>.empty(),
completer.complete,
);
final FlutterVmService flutterVmService = FlutterVmService(vmService);
unawaited(vmService.getSkSLs(
unawaited(flutterVmService.getSkSLs(
viewId: 'abc',
));
@ -266,12 +268,13 @@ void main() {
testWithoutContext('flushUIThreadTasks forwards arguments correctly', () async {
final Completer<String> completer = Completer<String>();
final vm_service.VmService vmService = vm_service.VmService(
final vm_service.VmService vmService = vm_service.VmService(
const Stream<String>.empty(),
completer.complete,
);
final FlutterVmService flutterVmService = FlutterVmService(vmService);
unawaited(vmService.flushUIThreadTasks(
unawaited(flutterVmService.flushUIThreadTasks(
uiIsolateId: 'def',
));
@ -449,13 +452,6 @@ void main() {
expect(fakeVmServiceHost.hasRemainingExpectations, false);
});
testWithoutContext('expandos are null safe', () {
vm_service.VmService vmService;
expect(vmService.httpAddress, null);
expect(vmService.wsAddress, null);
});
testWithoutContext('Can process log events from the vm service', () {
final vm_service.Event event = vm_service.Event(
bytes: base64.encode(utf8.encode('Hello There\n')),

View file

@ -15,6 +15,7 @@ import 'package:flutter_tools/src/base/user_messages.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/convert.dart';
import 'package:flutter_tools/src/doctor.dart';
import 'package:flutter_tools/src/vmservice.dart';
import 'package:vm_service/vm_service.dart' as vm_service;
import 'package:path/path.dart' as path; // ignore: package_path_import
@ -287,11 +288,13 @@ class NoContext implements AppContext {
class FakeVmServiceHost {
FakeVmServiceHost({
@required List<VmServiceExpectation> requests,
Uri httpAddress,
Uri wsAddress,
}) : _requests = requests {
_vmService = vm_service.VmService(
_vmService = FlutterVmService(vm_service.VmService(
_input.stream,
_output.add,
);
), httpAddress: httpAddress, wsAddress: wsAddress);
_applyStreamListen();
_output.stream.listen((String data) {
final Map<String, Object> request = json.decode(data) as Map<String, Object>;
@ -331,8 +334,9 @@ class FakeVmServiceHost {
final StreamController<String> _input = StreamController<String>();
final StreamController<String> _output = StreamController<String>();
vm_service.VmService get vmService => _vmService;
vm_service.VmService _vmService;
FlutterVmService get vmService => _vmService;
FlutterVmService _vmService;
bool get hasRemainingExpectations => _requests.isNotEmpty;