Skip to content

Commit 49a3152

Browse files
Handle a WebSocketException that may be thrown when closing the WebKit inspection protocol connection to Chrome (#151997)
Noticed this happening on macOS when the tool tries to shut down Chrome after all tabs have already been closed.
1 parent 7d5c1c0 commit 49a3152

File tree

2 files changed

+39
-17
lines changed

2 files changed

+39
-17
lines changed

packages/flutter_tools/lib/src/web/chrome.dart

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -507,20 +507,19 @@ class Chromium {
507507
// Send a command to shut down the browser cleanly.
508508
Duration sigtermDelay = Duration.zero;
509509
if (_hasValidChromeConnection) {
510-
ChromeTab? tab;
511510
try {
512-
tab = await chromeConnection.getTab(
511+
final ChromeTab? tab = await chromeConnection.getTab(
513512
(_) => true, retryFor: const Duration(seconds: 1));
514-
} on SocketException {
513+
if (tab != null) {
514+
final WipConnection wipConnection = await tab.connect();
515+
await wipConnection.sendCommand('Browser.close');
516+
await wipConnection.close();
517+
sigtermDelay = const Duration(seconds: 1);
518+
}
519+
} on IOException {
515520
// Chrome is not responding to the debug protocol and probably has
516521
// already been closed.
517522
}
518-
if (tab != null) {
519-
final WipConnection wipConnection = await tab.connect();
520-
await wipConnection.sendCommand('Browser.close');
521-
await wipConnection.close();
522-
sigtermDelay = const Duration(seconds: 1);
523-
}
524523
}
525524
chromeConnection.close();
526525
_hasValidChromeConnection = false;

packages/flutter_tools/test/web.shard/chrome_test.dart

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -838,6 +838,23 @@ void main() {
838838
chromeConnection.throwSocketExceptions = true;
839839
await chrome.close();
840840
});
841+
842+
test('Chromium close handles a WebSocketException when closing the WipConnection', () async {
843+
final BufferLogger logger = BufferLogger.test();
844+
final FakeChromeConnectionWithTab chromeConnection = FakeChromeConnectionWithTab(throwWebSocketException: true);
845+
final ChromiumLauncher chromiumLauncher = ChromiumLauncher(
846+
fileSystem: fileSystem,
847+
platform: platform,
848+
processManager: processManager,
849+
operatingSystemUtils: operatingSystemUtils,
850+
browserFinder: findChromeExecutable,
851+
logger: logger,
852+
);
853+
final FakeProcess process = FakeProcess();
854+
final Chromium chrome = Chromium(0, chromeConnection, chromiumLauncher: chromiumLauncher, process: process, logger: logger);
855+
expect(await chromiumLauncher.connect(chrome, false), equals(chrome));
856+
await chrome.close();
857+
});
841858
}
842859

843860
/// Fake chrome connection that fails to get tabs a few times.
@@ -877,8 +894,8 @@ typedef OnSendCommand = void Function(String);
877894

878895
/// Fake chrome connection that returns a tab.
879896
class FakeChromeConnectionWithTab extends Fake implements ChromeConnection {
880-
FakeChromeConnectionWithTab({OnSendCommand? onSendCommand})
881-
: _tab = FakeChromeTab(onSendCommand);
897+
FakeChromeConnectionWithTab({OnSendCommand? onSendCommand, bool throwWebSocketException = false})
898+
: _tab = FakeChromeTab(onSendCommand, throwWebSocketException);
882899

883900
final FakeChromeTab _tab;
884901
bool throwSocketExceptions = false;
@@ -904,20 +921,22 @@ class FakeChromeConnectionWithTab extends Fake implements ChromeConnection {
904921
}
905922

906923
class FakeChromeTab extends Fake implements ChromeTab {
907-
FakeChromeTab(this.onSendCommand);
924+
FakeChromeTab(this.onSendCommand, this.throwWebSocketException);
908925

909-
OnSendCommand? onSendCommand;
926+
final OnSendCommand? onSendCommand;
927+
final bool throwWebSocketException;
910928

911929
@override
912930
Future<WipConnection> connect({Function? onError}) async {
913-
return FakeWipConnection(onSendCommand);
931+
return FakeWipConnection(onSendCommand, throwWebSocketException);
914932
}
915933
}
916934

917935
class FakeWipConnection extends Fake implements WipConnection {
918-
FakeWipConnection(this.onSendCommand);
936+
FakeWipConnection(this.onSendCommand, this.throwWebSocketException);
919937

920-
OnSendCommand? onSendCommand;
938+
final OnSendCommand? onSendCommand;
939+
final bool throwWebSocketException;
921940

922941
@override
923942
Future<WipResponse> sendCommand(String method, [Map<String, dynamic>? params]) async {
@@ -926,5 +945,9 @@ class FakeWipConnection extends Fake implements WipConnection {
926945
}
927946

928947
@override
929-
Future<void> close() async {}
948+
Future<void> close() async {
949+
if (throwWebSocketException) {
950+
throw const io.WebSocketException('test');
951+
}
952+
}
930953
}

0 commit comments

Comments
 (0)