fix(macos): address PR #31 review findings
- _showLocalNetworkDeniedSnackBar: wrap Process.run with unawaited() and .catchError() so a rejected future (e.g. macOS sandbox refuses fork, or 'open' is missing) cannot bubble into the Flutter zone as an unhandled exception. The synchronous try/catch was a no-op because Process.run only throws asynchronously. - macos_permissions_service_test.dart: mirror the triggerLocalNetworkPrompt error-handling test with one for checkLocalNetworkAccess. Probe-path failures (NWConnection probe cannot establish, or Swift side throws) must fall back to cached state without crashing the caller. Tests: 186 passed, 2 skipped. Dart analyze clean.
This commit is contained in:
@@ -648,11 +648,18 @@ class _BetaHomeState extends State<_BetaHome> with WidgetsBindingObserver {
|
|||||||
action: SnackBarAction(
|
action: SnackBarAction(
|
||||||
label: l10n.networkPermissionOpenSettings,
|
label: l10n.networkPermissionOpenSettings,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
try {
|
// Fire-and-forget: don't block snackbar dismissal on the
|
||||||
Process.run('open', [
|
// child process. `Process.run` may throw synchronously
|
||||||
'x-apple.systempreferences:com.apple.preference.security?Privacy_LocalNetwork',
|
// (e.g. exec ENOENT) or return a future that rejects
|
||||||
]);
|
// (e.g. macOS denies fork); both paths are swallowed
|
||||||
} catch (_) {}
|
// because the user can still open Settings manually.
|
||||||
|
unawaited(
|
||||||
|
Future<void>(() async {
|
||||||
|
await Process.run('open', [
|
||||||
|
'x-apple.systempreferences:com.apple.preference.security?Privacy_LocalNetwork',
|
||||||
|
]);
|
||||||
|
}).catchError((_) {}),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -557,4 +557,30 @@ void main() {
|
|||||||
svc.dispose();
|
svc.dispose();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
test(
|
||||||
|
'SWE4-UV / SRS-300: checkLocalNetworkAccess() returns cached state '
|
||||||
|
'when the channel throws',
|
||||||
|
() async {
|
||||||
|
final svc = MacOSPermissionsService(channel: channel)..start();
|
||||||
|
|
||||||
|
outgoingResponder = (call) async {
|
||||||
|
if (call.method == methodCheckLocalNetworkAccess) {
|
||||||
|
throw PlatformException(code: 'probe-failed');
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Probe path failures (e.g. NWConnection couldn't establish a
|
||||||
|
// listener, or the Swift side threw) must not crash callers
|
||||||
|
// — they must fall back to whatever the service already cached.
|
||||||
|
final result = await svc.checkLocalNetworkAccess(
|
||||||
|
host: '127.0.0.1',
|
||||||
|
port: 9987,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result, isNotNull);
|
||||||
|
svc.dispose();
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user