Add publish-port flag to disable mDNS port discovery (#67452)
diff --git a/packages/flutter_tools/lib/src/commands/drive.dart b/packages/flutter_tools/lib/src/commands/drive.dart index f3c520f..7fa8e81 100644 --- a/packages/flutter_tools/lib/src/commands/drive.dart +++ b/packages/flutter_tools/lib/src/commands/drive.dart
@@ -55,6 +55,11 @@ }) { requiresPubspecYaml(); addEnableExperimentation(hide: !verboseHelp); + + // By default, the drive app should not publish the VM service port over mDNS + // to prevent a local network permission dialog on iOS 14+, + // which cannot be accepted or dismissed in a CI environment. + addPublishPort(enabledByDefault: false, verboseHelp: verboseHelp); argParser ..addFlag('keep-app-running', defaultsTo: null, @@ -215,7 +220,8 @@ ) : DebuggingOptions.enabled( getBuildInfo(), - port: stringArg('web-port') + port: stringArg('web-port'), + disablePortPublication: disablePortPublication, ), stayResident: false, urlTunneller: null, @@ -501,6 +507,7 @@ command.getBuildInfo(), startPaused: true, hostVmServicePort: webUri != null ? command.hostVmservicePort : 0, + disablePortPublication: command.disablePortPublication, ddsPort: command.ddsPort, verboseSystemLogs: command.verboseSystemLogs, cacheSkSL: command.cacheSkSL,
diff --git a/packages/flutter_tools/lib/src/commands/run.dart b/packages/flutter_tools/lib/src/commands/run.dart index 63c00d2..092abe1 100644 --- a/packages/flutter_tools/lib/src/commands/run.dart +++ b/packages/flutter_tools/lib/src/commands/run.dart
@@ -97,6 +97,11 @@ usesFilesystemOptions(hide: !verboseHelp); usesExtraFrontendOptions(); addEnableExperimentation(hide: !verboseHelp); + + // By default, the app should to publish the VM service port over mDNS. + // This will allow subsequent "flutter attach" commands to connect to the VM + // without needing to know the port. + addPublishPort(enabledByDefault: true, verboseHelp: verboseHelp); argParser ..addFlag('start-paused', negatable: false, @@ -407,6 +412,7 @@ purgePersistentCache: purgePersistentCache, deviceVmServicePort: deviceVmservicePort, hostVmServicePort: hostVmservicePort, + disablePortPublication: disablePortPublication, ddsPort: ddsPort, verboseSystemLogs: boolArg('verbose-system-logs'), initializePlatform: boolArg('web-initialize-platform'),
diff --git a/packages/flutter_tools/lib/src/device.dart b/packages/flutter_tools/lib/src/device.dart index 769b0ee..92d4ebf 100644 --- a/packages/flutter_tools/lib/src/device.dart +++ b/packages/flutter_tools/lib/src/device.dart
@@ -813,6 +813,7 @@ this.useTestFonts = false, this.verboseSystemLogs = false, this.hostVmServicePort, + this.disablePortPublication = false, this.deviceVmServicePort, this.ddsPort, this.initializePlatform = true, @@ -855,6 +856,7 @@ purgePersistentCache = false, verboseSystemLogs = false, hostVmServicePort = null, + disablePortPublication = false, deviceVmServicePort = null, ddsPort = null, vmserviceOutFile = null, @@ -884,6 +886,7 @@ final bool initializePlatform; final int hostVmServicePort; final int deviceVmServicePort; + final bool disablePortPublication; final int ddsPort; final String port; final String hostname;
diff --git a/packages/flutter_tools/lib/src/ios/devices.dart b/packages/flutter_tools/lib/src/ios/devices.dart index a7b0abd..e8e053b 100644 --- a/packages/flutter_tools/lib/src/ios/devices.dart +++ b/packages/flutter_tools/lib/src/ios/devices.dart
@@ -22,7 +22,6 @@ import '../device.dart'; import '../globals.dart' as globals; import '../macos/xcode.dart'; -import '../mdns_discovery.dart'; import '../project.dart'; import '../protocol_discovery.dart'; import '../vmservice.dart'; @@ -369,6 +368,7 @@ '--enable-service-port-fallback', '--disable-service-auth-codes', '--observatory-port=$assumedObservatoryPort', + if (debuggingOptions.disablePortPublication) '--disable-observatory-publication', if (debuggingOptions.startPaused) '--start-paused', if (dartVmFlags.isNotEmpty) '--dart-flags="$dartVmFlags"', if (debuggingOptions.useTestFonts) '--use-test-fonts', @@ -453,7 +453,6 @@ _logger.printTrace('Application launched on the device. Waiting for observatory port.'); final FallbackDiscovery fallbackDiscovery = FallbackDiscovery( logger: _logger, - mDnsObservatoryDiscovery: MDnsObservatoryDiscovery.instance, portForwarder: portForwarder, protocolDiscovery: observatoryDiscovery, flutterUsage: globals.flutterUsage,
diff --git a/packages/flutter_tools/lib/src/ios/fallback_discovery.dart b/packages/flutter_tools/lib/src/ios/fallback_discovery.dart index b321114..127c0fc 100644 --- a/packages/flutter_tools/lib/src/ios/fallback_discovery.dart +++ b/packages/flutter_tools/lib/src/ios/fallback_discovery.dart
@@ -8,7 +8,6 @@ import '../base/io.dart'; import '../base/logger.dart'; import '../device.dart'; -import '../mdns_discovery.dart'; import '../protocol_discovery.dart'; import '../reporting/reporting.dart'; @@ -17,36 +16,23 @@ /// A protocol for discovery of a vmservice on an attached iOS device with /// multiple fallbacks. /// -/// On versions of iOS 13 and greater, libimobiledevice can no longer listen to -/// logs directly. The only way to discover an active observatory is through the -/// mDNS protocol. However, there are a number of circumstances where this breaks -/// down, such as when the device is connected to certain wifi networks or with -/// certain hotspot connections enabled. -/// -/// Another approach to discover a vmservice is to attempt to assign a +/// First, it tries to discover a vmservice by assigning a /// specific port and then attempt to connect. This may fail if the port is /// not available. This port value should be either random, or otherwise /// generated with application specific input. This reduces the chance of /// accidentally connecting to another running flutter application. /// -/// Finally, if neither of the above approaches works, we can still attempt -/// to parse logs. -/// -/// To improve the overall resilience of the process, this class combines the -/// three discovery strategies. First it assigns a port and attempts to connect. -/// Then if this fails it falls back to mDNS, then finally attempting to scan -/// logs. +/// If that does not work, attempt to scan logs from the attached debugger +/// and parse the connected port logged by the engine. class FallbackDiscovery { FallbackDiscovery({ @required DevicePortForwarder portForwarder, - @required MDnsObservatoryDiscovery mDnsObservatoryDiscovery, @required Logger logger, @required ProtocolDiscovery protocolDiscovery, @required Usage flutterUsage, @required VmServiceConnector vmServiceConnectUri, Duration pollingDelay, }) : _logger = logger, - _mDnsObservatoryDiscovery = mDnsObservatoryDiscovery, _portForwarder = portForwarder, _protocolDiscovery = protocolDiscovery, _flutterUsage = flutterUsage, @@ -56,7 +42,6 @@ static const String _kEventName = 'ios-handshake'; final DevicePortForwarder _portForwarder; - final MDnsObservatoryDiscovery _mDnsObservatoryDiscovery; final Logger _logger; final ProtocolDiscovery _protocolDiscovery; final Usage _flutterUsage; @@ -97,37 +82,13 @@ } on Exception catch (err) { _logger.printTrace(err.toString()); } - _logger.printTrace('Failed to connect with log scanning, falling back to mDNS'); + _logger.printTrace('Failed to connect with log scanning'); UsageEvent( _kEventName, 'log-failure', flutterUsage: _flutterUsage, ).send(); - try { - final Uri result = await _mDnsObservatoryDiscovery.getObservatoryUri( - packageId, - device, - usesIpv6: usesIpv6, - hostVmservicePort: hostVmservicePort, - ); - if (result != null) { - UsageEvent( - _kEventName, - 'mdns-success', - flutterUsage: _flutterUsage, - ).send(); - return result; - } - } on Exception catch (err) { - _logger.printTrace(err.toString()); - } - _logger.printTrace('Failed to connect with mDNS'); - UsageEvent( - _kEventName, - 'mdns-failure', - flutterUsage: _flutterUsage, - ).send(); return null; } @@ -200,7 +161,7 @@ await Future<void>.delayed(_pollingDelay); attempts += 1; } - _logger.printTrace('Failed to connect directly, falling back to mDNS'); + _logger.printTrace('Failed to connect directly, falling back to log scanning'); _sendFailureEvent(firstException, assumedDevicePort); return null; }
diff --git a/packages/flutter_tools/lib/src/mdns_discovery.dart b/packages/flutter_tools/lib/src/mdns_discovery.dart index 3375e8d..ac76abd 100644 --- a/packages/flutter_tools/lib/src/mdns_discovery.dart +++ b/packages/flutter_tools/lib/src/mdns_discovery.dart
@@ -51,6 +51,7 @@ /// it will return that instance's information regardless of what application /// the Observatory instance is for. // TODO(jonahwilliams): use `deviceVmservicePort` to filter mdns results. + @visibleForTesting Future<MDnsObservatoryDiscoveryResult> query({String applicationId, int deviceVmservicePort}) async { globals.printTrace('Checking for advertised Dart observatories...'); try {
diff --git a/packages/flutter_tools/lib/src/runner/flutter_command.dart b/packages/flutter_tools/lib/src/runner/flutter_command.dart index 1e3ab0f..7003262 100644 --- a/packages/flutter_tools/lib/src/runner/flutter_command.dart +++ b/packages/flutter_tools/lib/src/runner/flutter_command.dart
@@ -369,6 +369,17 @@ return null; } + void addPublishPort({ bool enabledByDefault = true, bool verboseHelp = false }) { + argParser.addFlag('publish-port', + negatable: true, + hide: !verboseHelp, + help: 'Publish the VM service port over mDNS. Disable to prevent the' + 'local network permission app dialog in debug and profile build modes (iOS devices only.)', + defaultsTo: enabledByDefault); + } + + bool get disablePortPublication => !boolArg('publish-port'); + void usesIpv6Flag() { argParser.addFlag(ipv6Flag, hide: true,