mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Hide error on mDNS registration failure and print warning in flutter attach (#166782)
Publishing an mDNS service stopped working on macOS 15.4 for the iOS Simulator. `DNSServiceRegister` always returns a callback with error code `kDNSServiceErr_PolicyDenied`, as if the user had rejected the permissions popup (except no popup is ever shown). mDNS is used to discover the Dart VM when running `flutter attach`. This PR does not display the error message when `DNSServiceRegister` fails for iOS Simulators. Instead, it prints a warning if `flutter attach` takes too long with instructions to either use `--debug-url` or to run `flutter attach` before running the app. If `DNSServiceRegister` works again in a future macOS update, mDNS will continue to work the way it did previously. Workaround for https://github.com/flutter/flutter/issues/166333. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
This commit is contained in:
parent
fbed8a7194
commit
ecabb1a052
@ -76,8 +76,6 @@ FLUTTER_ASSERT_ARC
|
||||
}
|
||||
|
||||
- (void)publishServiceProtocolPort:(NSURL*)url {
|
||||
// TODO(vashworth): Remove once done debugging https://github.com/flutter/flutter/issues/129836
|
||||
FML_LOG(INFO) << "Publish Service Protocol Port";
|
||||
DNSServiceFlags flags = kDNSServiceFlagsDefault;
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
// Simulator needs to use local loopback explicitly to work.
|
||||
@ -126,10 +124,20 @@ static void DNSSD_API RegistrationCallback(DNSServiceRef sdRef,
|
||||
if (errorCode == kDNSServiceErr_NoError) {
|
||||
FML_DLOG(INFO) << "FlutterDartVMServicePublisher is ready!";
|
||||
} else if (errorCode == kDNSServiceErr_PolicyDenied) {
|
||||
// Local Network permissions on simulators stopped working in macOS 15.4 and will always return
|
||||
// kDNSServiceErr_PolicyDenied. See
|
||||
// https://github.com/flutter/flutter/issues/166333#issuecomment-2786720560.
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
FML_DLOG(WARNING)
|
||||
<< "Could not register as server for FlutterDartVMServicePublisher, permission "
|
||||
<< "denied. Check your 'Local Network' permissions for this app in the Privacy section of "
|
||||
<< "the system Settings.";
|
||||
#else // TARGET_IPHONE_SIMULATOR
|
||||
FML_LOG(ERROR)
|
||||
<< "Could not register as server for FlutterDartVMServicePublisher, permission "
|
||||
<< "denied. Check your 'Local Network' permissions for this app in the Privacy section of "
|
||||
<< "the system Settings.";
|
||||
#endif // TARGET_IPHONE_SIMULATOR
|
||||
} else {
|
||||
FML_LOG(ERROR) << "Could not register as server for FlutterDartVMServicePublisher. Check your "
|
||||
"network settings and relaunch the application.";
|
||||
|
@ -867,8 +867,6 @@ static void SetEntryPoint(flutter::Settings* settings, NSString* entrypoint, NSS
|
||||
FML_LOG(ERROR) << "Could not start a shell FlutterEngine with entrypoint: "
|
||||
<< entrypoint.UTF8String;
|
||||
} else {
|
||||
// TODO(vashworth): Remove once done debugging https://github.com/flutter/flutter/issues/129836
|
||||
FML_LOG(INFO) << "Enabled VM Service Publication: " << settings.enable_vm_service_publication;
|
||||
[self setUpShell:std::move(shell)
|
||||
withVMServicePublication:settings.enable_vm_service_publication];
|
||||
if ([FlutterEngine isProfilerEnabled]) {
|
||||
|
@ -23,6 +23,7 @@ import '../device.dart';
|
||||
import '../device_port_forwarder.dart';
|
||||
import '../device_vm_service_discovery_for_attach.dart';
|
||||
import '../ios/devices.dart';
|
||||
import '../ios/simulators.dart';
|
||||
import '../macos/macos_ipad_device.dart';
|
||||
import '../mdns_discovery.dart';
|
||||
import '../project.dart';
|
||||
@ -316,8 +317,20 @@ known, it can be explicitly provided to attach via the command-line, e.g.
|
||||
final Status discoveryStatus = _logger.startSpinner(
|
||||
timeout: const Duration(seconds: 30),
|
||||
slowWarningCallback: () {
|
||||
// On iOS we rely on mDNS to find Dart VM Service. Remind the user to allow local network permissions on the device.
|
||||
if (_isIOSDevice(device)) {
|
||||
// On iOS we rely on mDNS to find Dart VM Service.
|
||||
if (device is IOSSimulator) {
|
||||
// mDNS on simulators stopped working in macOS 15.4.
|
||||
// See https://github.com/flutter/flutter/issues/166333.
|
||||
return 'The Dart VM Service was not discovered after 30 seconds. '
|
||||
'This may be due to limited mDNS support in the iOS Simulator.\n\n'
|
||||
'Click "Allow" to the prompt on your device asking if you would like to find and connect devices on your local network. '
|
||||
'If you selected "Don\'t Allow", you can turn it on in Settings > Your App Name > Local Network. '
|
||||
"If you don't see your app in the Settings, uninstall the app and rerun to see the prompt again.\n\n"
|
||||
'If you do not receive a prompt, either run "flutter attach" before starting the '
|
||||
'app or use the Dart VM service URL from the Xcode console with '
|
||||
'"flutter attach --debug-url=<URL>".\n';
|
||||
} else if (_isIOSDevice(device)) {
|
||||
// Remind the user to allow local network permissions on the device.
|
||||
return 'The Dart VM Service was not discovered after 30 seconds. This is taking much longer than expected...\n\n'
|
||||
'Click "Allow" to the prompt on your device asking if you would like to find and connect devices on your local network. '
|
||||
'If you selected "Don\'t Allow", you can turn it on in Settings > Your App Name > Local Network. '
|
||||
@ -326,6 +339,7 @@ known, it can be explicitly provided to attach via the command-line, e.g.
|
||||
|
||||
return 'The Dart VM Service was not discovered after 30 seconds. This is taking much longer than expected...\n';
|
||||
},
|
||||
warningColor: TerminalColor.cyan,
|
||||
);
|
||||
|
||||
vmServiceUri = vmServiceDiscovery.uris;
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:fake_async/fake_async.dart';
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:flutter_tools/src/android/android_device.dart';
|
||||
import 'package:flutter_tools/src/application_package.dart';
|
||||
@ -25,6 +26,7 @@ import 'package:flutter_tools/src/device_port_forwarder.dart';
|
||||
import 'package:flutter_tools/src/device_vm_service_discovery_for_attach.dart';
|
||||
import 'package:flutter_tools/src/ios/application_package.dart';
|
||||
import 'package:flutter_tools/src/ios/devices.dart';
|
||||
import 'package:flutter_tools/src/ios/simulators.dart';
|
||||
import 'package:flutter_tools/src/macos/macos_ipad_device.dart';
|
||||
import 'package:flutter_tools/src/mdns_discovery.dart';
|
||||
import 'package:flutter_tools/src/project.dart';
|
||||
@ -1528,6 +1530,52 @@ void main() {
|
||||
DeviceManager: () => testDeviceManager,
|
||||
},
|
||||
);
|
||||
|
||||
group('prints warning when too slow', () {
|
||||
late SlowWarningCallbackBufferLogger logger;
|
||||
|
||||
setUp(() {
|
||||
logger = SlowWarningCallbackBufferLogger.test();
|
||||
});
|
||||
|
||||
testUsingContext(
|
||||
'to find on iOS Simulator',
|
||||
() async {
|
||||
final FakeIOSSimulator device = FakeIOSSimulator();
|
||||
testDeviceManager.devices = <Device>[device];
|
||||
FakeAsync().run((FakeAsync fakeAsync) {
|
||||
createTestCommandRunner(
|
||||
AttachCommand(
|
||||
stdio: stdio,
|
||||
logger: logger,
|
||||
terminal: terminal,
|
||||
signals: signals,
|
||||
platform: platform,
|
||||
processInfo: processInfo,
|
||||
fileSystem: testFileSystem,
|
||||
),
|
||||
).run(<String>['attach']);
|
||||
|
||||
logger.expectedWarning =
|
||||
'The Dart VM Service was not discovered after 30 seconds. '
|
||||
'This may be due to limited mDNS support in the iOS Simulator.\n\n'
|
||||
'Click "Allow" to the prompt on your device asking if you would like to find and connect devices on your local network. '
|
||||
'If you selected "Don\'t Allow", you can turn it on in Settings > Your App Name > Local Network. '
|
||||
"If you don't see your app in the Settings, uninstall the app and rerun to see the prompt again.\n\n"
|
||||
'If you do not receive a prompt, either run "flutter attach" before starting the '
|
||||
'app or use the Dart VM service URL from the Xcode console with '
|
||||
'"flutter attach --debug-url=<URL>".\n';
|
||||
fakeAsync.elapse(const Duration(seconds: 30));
|
||||
});
|
||||
},
|
||||
overrides: <Type, Generator>{
|
||||
FileSystem: () => testFileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
Logger: () => logger,
|
||||
DeviceManager: () => testDeviceManager,
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -1966,6 +2014,62 @@ class FakeIOSDevice extends Fake implements IOSDevice {
|
||||
}
|
||||
}
|
||||
|
||||
class FakeIOSSimulator extends Fake implements IOSSimulator {
|
||||
@override
|
||||
final String name = 'name';
|
||||
|
||||
@override
|
||||
String get displayName => name;
|
||||
|
||||
@override
|
||||
bool isSupported() => true;
|
||||
|
||||
@override
|
||||
bool isSupportedForProject(FlutterProject flutterProject) => true;
|
||||
|
||||
@override
|
||||
bool get isConnected => true;
|
||||
|
||||
@override
|
||||
DeviceConnectionInterface get connectionInterface => DeviceConnectionInterface.attached;
|
||||
|
||||
@override
|
||||
bool get ephemeral => true;
|
||||
|
||||
@override
|
||||
Future<TargetPlatform> get targetPlatform async => TargetPlatform.ios;
|
||||
|
||||
@override
|
||||
final PlatformType platformType = PlatformType.ios;
|
||||
|
||||
@override
|
||||
bool get isWirelesslyConnected => false;
|
||||
|
||||
@override
|
||||
DevicePortForwarder portForwarder = RecordingPortForwarder();
|
||||
|
||||
@override
|
||||
VMServiceDiscoveryForAttach getVMServiceDiscoveryForAttach({
|
||||
String? appId,
|
||||
String? fuchsiaModule,
|
||||
int? filterDevicePort,
|
||||
int? expectedHostPort,
|
||||
required bool ipv6,
|
||||
required Logger logger,
|
||||
}) {
|
||||
final MdnsVMServiceDiscoveryForAttach mdnsVMServiceDiscoveryForAttach =
|
||||
MdnsVMServiceDiscoveryForAttach(
|
||||
device: this,
|
||||
appId: appId,
|
||||
deviceVmservicePort: filterDevicePort,
|
||||
hostVmservicePort: expectedHostPort,
|
||||
usesIpv6: ipv6,
|
||||
useDeviceIPAsHost: isWirelesslyConnected,
|
||||
);
|
||||
return mdnsVMServiceDiscoveryForAttach;
|
||||
}
|
||||
}
|
||||
|
||||
class FakeMDnsClient extends Fake implements MDnsClient {
|
||||
FakeMDnsClient(
|
||||
this.ptrRecords,
|
||||
@ -2054,3 +2158,21 @@ class FakeTerminal extends Fake implements AnsiTerminal {
|
||||
@override
|
||||
Stream<String> get keystrokes => StreamController<String>().stream;
|
||||
}
|
||||
|
||||
class SlowWarningCallbackBufferLogger extends BufferLogger {
|
||||
SlowWarningCallbackBufferLogger.test() : super.test();
|
||||
|
||||
String? expectedWarning;
|
||||
|
||||
@override
|
||||
Status startSpinner({
|
||||
VoidCallback? onFinish,
|
||||
Duration? timeout,
|
||||
SlowWarningCallback? slowWarningCallback,
|
||||
TerminalColor? warningColor,
|
||||
}) {
|
||||
expect(slowWarningCallback, isNotNull);
|
||||
expect(slowWarningCallback!(), expectedWarning);
|
||||
return SilentStatus(stopwatch: Stopwatch(), onFinish: onFinish)..start();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user