/
magnusroot
/
flutter
Обзор
Документация
Войти
/
magnusroot
/
flutter
Код
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
packages/flutter_tools/lib/src/base/dds.dart
284 строки
9 KB
flutteractionsbot
Revert: Split the platform and cpuArch part of TargetPlatform (#190258)
30 июл 2026, 08:44
Не верифицирован
30 июл 2026, 08:44
ddb43a3
Код
Авторство
О чём код?
// Copyright 2014 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import 'dart:async'; import 'package:browser_launcher/browser_launcher.dart'; import 'package:dds/dds.dart'; import 'package:dds/dds_launcher.dart'; import 'package:meta/meta.dart'; import '../artifacts.dart'; import '../build_info.dart'; import '../device.dart'; import '../globals.dart' as globals; import '../resident_runner.dart'; import '../vmservice.dart'; import 'io.dart' as io; import 'logger.dart'; import 'utils.dart'; export 'package:dds/dds.dart' show DartDevelopmentServiceException, ExistingDartDevelopmentServiceException; typedef DDSLauncherCallback = Future<DartDevelopmentServiceLauncher> Function({ required Uri remoteVmServiceUri, String? appName, Uri? serviceUri, bool enableAuthCodes, bool serveDevTools, Uri? devToolsServerAddress, bool enableServicePortFallback, List<String> cachedUserTags, String? dartExecutable, String? google3WorkspaceRoot, }); typedef StartChromeCallback = Future<io.Process> Function(List<String> urls, {List<String> args}); // TODO(fujino): This should be direct injected, rather than mutable global state. /// Used by tests to override the DDS spawn behavior for mocking purposes. @visibleForTesting DDSLauncherCallback ddsLauncherCallback = DartDevelopmentServiceLauncher.start; /// Helper class to launch a [DartDevelopmentServiceLauncher]. Allows for us to /// mock out this functionality for testing purposes. class DartDevelopmentService with DartDevelopmentServiceLocalOperationsMixin { DartDevelopmentService({required this.logger}); DartDevelopmentServiceLauncher? _ddsInstance; @override Uri? get uri => _ddsInstance?.uri ?? _existingDdsUri; Uri? _existingDdsUri; @override Uri? get devToolsUri => _ddsInstance?.devToolsUri; Uri? get dtdUri => _ddsInstance?.dtdUri; Future<void> get done => _completer.future; final _completer = Completer<void>(); @override final Logger logger; @override Future<void> startDartDevelopmentService( Uri vmServiceUri, { String? appName, int? ddsPort, bool? disableServiceAuthCodes, bool? ipv6, bool enableDevTools = true, bool cacheStartupProfile = false, String? google3WorkspaceRoot, Uri? devToolsServerAddress, }) async { assert(_ddsInstance == null); final ddsUri = Uri( scheme: 'http', host: ((ipv6 ?? false) ? io.InternetAddress.loopbackIPv6 : io.InternetAddress.loopbackIPv4) .host, port: ddsPort ?? 0, ); logger.printTrace( 'Launching a Dart Developer Service (DDS) instance at $ddsUri, ' 'connecting to VM service at $vmServiceUri.', ); void completeFuture() { if (!_completer.isCompleted) { _completer.complete(); } } try { _ddsInstance = await ddsLauncherCallback( appName: appName, remoteVmServiceUri: vmServiceUri, serviceUri: ddsUri, enableAuthCodes: disableServiceAuthCodes != true, // Enables caching of CPU samples collected during application startup. cachedUserTags: cacheStartupProfile ? const <String>['AppStartUp'] : const <String>[], serveDevTools: enableDevTools, devToolsServerAddress: devToolsServerAddress, google3WorkspaceRoot: google3WorkspaceRoot, dartExecutable: globals.artifacts!.getArtifactPath(Artifact.engineDartBinary), ); unawaited(_ddsInstance!.done.whenComplete(completeFuture)); } on DartDevelopmentServiceException catch (e) { logger.printTrace('Warning: Failed to start DDS: ${e.message}'); if (e is ExistingDartDevelopmentServiceException) { _existingDdsUri = e.ddsUri; } completeFuture(); rethrow; } } Future<void> shutdown() async { await _ddsInstance?.shutdown(); } } /// Contains common functionality that can be used with any implementation of /// [DartDevelopmentService]. mixin DartDevelopmentServiceLocalOperationsMixin { Uri? get uri; Uri? get devToolsUri; Logger get logger; /// Used to confirm `launchDevToolsInBrowser` is called in tests. @visibleForTesting bool get calledLaunchDevToolsInBrowser => _calledLaunchDevToolsInBrowser; var _calledLaunchDevToolsInBrowser = false; Future<void> startDartDevelopmentService( Uri vmServiceUri, { String? appName, int? ddsPort, bool? disableServiceAuthCodes, bool? ipv6, bool enableDevTools = true, bool cacheStartupProfile = false, String? google3WorkspaceRoot, Uri? devToolsServerAddress, }); /// A convenience method used to create a [DartDevelopmentService] instance /// from a [DebuggingOptions] instance. Future<void> startDartDevelopmentServiceFromDebuggingOptions( Uri vmServiceUri, { String? appName, required DebuggingOptions debuggingOptions, }) => startDartDevelopmentService( vmServiceUri, appName: appName, ddsPort: debuggingOptions.ddsPort, disableServiceAuthCodes: debuggingOptions.disableServiceAuthCodes, ipv6: debuggingOptions.ipv6, enableDevTools: debuggingOptions.enableDevTools, cacheStartupProfile: debuggingOptions.cacheStartupProfile, google3WorkspaceRoot: debuggingOptions.google3WorkspaceRoot, devToolsServerAddress: debuggingOptions.devToolsServerAddress, ); /// Launches a DevTools instance connected to the DDS instance connected to /// [device] in Chrome. bool launchDevToolsInBrowser( FlutterDevice device, { @visibleForTesting StartChromeCallback startChrome = Chrome.start, }) { _calledLaunchDevToolsInBrowser = true; if (devToolsUri == null) { return false; } assert(devToolsUri != null); logger.printStatus('Launching Flutter DevTools for ${device.device!.name} at $devToolsUri'); unawaited(startChrome(<String>[devToolsUri!.toString()])); return true; } /// Re-initializes Flutter framework service extension state after a hot /// restart. Future<void> handleHotRestart(FlutterDevice? device) => invokeServiceExtensions(device); /// Initializes Flutter framework service extension state related to DevTools /// and VM service connection information. Future<void> invokeServiceExtensions(FlutterDevice? device) async { await Future.wait(<Future<void>>[ maybeCallDevToolsUriServiceExtension(device: device, uri: devToolsUri), _callConnectedVmServiceUriExtension(device), ]); } /// Returns null if the service extension cannot be found on the device. Future<bool> _waitForExtensionsForDevice(FlutterDevice flutterDevice, String extension) async { try { await flutterDevice.vmService?.findExtensionIsolate(extension); return true; } on VmServiceDisappearedException { logger.printTrace( 'The VM Service for ${flutterDevice.device} disappeared while trying to' ' find the $extension service extension. Skipping subsequent DevTools ' 'setup for this device.', ); return false; } } /// Sets the DevTools URI in the Flutter framework, used for deep linking /// support. Future<void> maybeCallDevToolsUriServiceExtension({ required FlutterDevice? device, required Uri? uri, }) async { if (uri != null && device?.vmService != null) { // We're only setting the URI pointing to where DevTools is being served from. Don't include // any query parameters, including those used to automatically connect to the application. if (uri.hasQuery) { uri = uri.withoutQueryParameters(); } await _callDevToolsUriExtension(device!, uri); } } Future<void> _callDevToolsUriExtension(FlutterDevice device, Uri uri) async { try { await _invokeRpcOnFirstView( 'ext.flutter.activeDevToolsServerAddress', device: device, params: <String, dynamic>{'value': uri.toString()}, ); } on Exception catch (e) { logger.printError( 'Failed to set DevTools server address: $e. Deep links to' ' DevTools will not show in Flutter errors.', ); } } Future<void> _callConnectedVmServiceUriExtension(FlutterDevice? device) async { if (device == null || uri == null) { return; } try { await _invokeRpcOnFirstView( 'ext.flutter.connectedVmServiceUri', device: device, params: <String, dynamic>{'value': uri.toString()}, ); } on Exception catch (e) { logger.printError(e.toString()); logger.printError( 'Failed to set vm service URI: $e. Deep links to DevTools' ' will not show in Flutter errors.', ); } } Future<void> _invokeRpcOnFirstView( String method, { required FlutterDevice device, required Map<String, dynamic> params, }) async { if (!(await _waitForExtensionsForDevice(device, method))) { return; } if (device.targetPlatform == TargetPlatform.web_javascript) { await device.vmService!.callMethodWrapper(method, args: params); return; } final List<FlutterView> views = await device.vmService!.getFlutterViews(); if (views.isEmpty) { return; } await device.vmService!.invokeFlutterExtensionRpcRaw( method, args: params, isolateId: views.first.uiIsolate!.id, ); } }