Don't crash flutter tool if Chrome is not available (#154941)
Instead of unawaiting the future, let's ignore it. Fixes issue #154940 I am not sure if tests would be required for this change or not. ## Pre-launch Checklist - [ ] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [ ] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [ ] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [ ] I signed the [CLA]. - [ ] I listed at least one issue that this PR fixes in the description above. - [ ] I updated/added relevant documentation (doc comments with `///`). - [ ] I added new tests to check the change I am making, or this PR is [test-exempt]. - [ ] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [ ] 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 --------- Co-authored-by: Christopher Fujino <christopherfujino@gmail.com> Co-authored-by: Andrew Kolos <andrewrkolos@gmail.com> Co-authored-by: Ben Konyi <bkonyi@google.com>
This commit is contained in:
parent
539727fb9d
commit
cc44dba520
@ -8,23 +8,25 @@
|
|||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:browser_launcher/browser_launcher.dart';
|
|
||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
|
|
||||||
|
import 'base/io.dart';
|
||||||
import 'base/logger.dart';
|
import 'base/logger.dart';
|
||||||
import 'build_info.dart';
|
import 'build_info.dart';
|
||||||
import 'resident_runner.dart';
|
import 'resident_runner.dart';
|
||||||
import 'vmservice.dart';
|
import 'vmservice.dart';
|
||||||
|
import 'web/chrome.dart';
|
||||||
|
|
||||||
typedef ResidentDevtoolsHandlerFactory =
|
typedef ResidentDevtoolsHandlerFactory =
|
||||||
ResidentDevtoolsHandler Function(DevtoolsLauncher?, ResidentRunner, Logger);
|
ResidentDevtoolsHandler Function(DevtoolsLauncher?, ResidentRunner, Logger, ChromiumLauncher);
|
||||||
|
|
||||||
ResidentDevtoolsHandler createDefaultHandler(
|
ResidentDevtoolsHandler createDefaultHandler(
|
||||||
DevtoolsLauncher? launcher,
|
DevtoolsLauncher? launcher,
|
||||||
ResidentRunner runner,
|
ResidentRunner runner,
|
||||||
Logger logger,
|
Logger logger,
|
||||||
|
ChromiumLauncher chromiumLauncher,
|
||||||
) {
|
) {
|
||||||
return FlutterResidentDevtoolsHandler(launcher, runner, logger);
|
return FlutterResidentDevtoolsHandler(launcher, runner, logger, chromiumLauncher);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper class to manage the life-cycle of devtools and its interaction with
|
/// Helper class to manage the life-cycle of devtools and its interaction with
|
||||||
@ -66,12 +68,18 @@ abstract class ResidentDevtoolsHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class FlutterResidentDevtoolsHandler implements ResidentDevtoolsHandler {
|
class FlutterResidentDevtoolsHandler implements ResidentDevtoolsHandler {
|
||||||
FlutterResidentDevtoolsHandler(this._devToolsLauncher, this._residentRunner, this._logger);
|
FlutterResidentDevtoolsHandler(
|
||||||
|
this._devToolsLauncher,
|
||||||
|
this._residentRunner,
|
||||||
|
this._logger,
|
||||||
|
this._chromiumLauncher,
|
||||||
|
);
|
||||||
|
|
||||||
static const Duration launchInBrowserTimeout = Duration(seconds: 15);
|
static const Duration launchInBrowserTimeout = Duration(seconds: 15);
|
||||||
|
|
||||||
final DevtoolsLauncher? _devToolsLauncher;
|
final DevtoolsLauncher? _devToolsLauncher;
|
||||||
final ResidentRunner _residentRunner;
|
final ResidentRunner _residentRunner;
|
||||||
|
final ChromiumLauncher _chromiumLauncher;
|
||||||
final Logger _logger;
|
final Logger _logger;
|
||||||
bool _shutdown = false;
|
bool _shutdown = false;
|
||||||
|
|
||||||
@ -184,11 +192,14 @@ class FlutterResidentDevtoolsHandler implements ResidentDevtoolsHandler {
|
|||||||
queryParameters: <String, dynamic>{'uri': '${device!.vmService!.httpAddress}'},
|
queryParameters: <String, dynamic>{'uri': '${device!.vmService!.httpAddress}'},
|
||||||
)
|
)
|
||||||
.toString();
|
.toString();
|
||||||
_logger.printStatus(
|
_logger.printStatus('Launching Flutter DevTools for ${device.device!.name} at $devToolsUrl');
|
||||||
'Launching Flutter DevTools for '
|
|
||||||
'${device.device!.displayName} at $devToolsUrl',
|
_chromiumLauncher.launch(devToolsUrl).catchError((Object e) {
|
||||||
);
|
_logger.printError('Failed to launch web browser: $e');
|
||||||
unawaited(Chrome.start(<String>[devToolsUrl]));
|
throw ProcessException('Chrome', <String>[
|
||||||
|
devToolsUrl,
|
||||||
|
], 'Failed to launch browser for dev tools');
|
||||||
|
}).ignore();
|
||||||
}
|
}
|
||||||
launchedInBrowser = true;
|
launchedInBrowser = true;
|
||||||
}
|
}
|
||||||
@ -316,6 +327,7 @@ NoOpDevtoolsHandler createNoOpHandler(
|
|||||||
DevtoolsLauncher? launcher,
|
DevtoolsLauncher? launcher,
|
||||||
ResidentRunner runner,
|
ResidentRunner runner,
|
||||||
Logger logger,
|
Logger logger,
|
||||||
|
ChromiumLauncher? chromiumLauncher,
|
||||||
) {
|
) {
|
||||||
return NoOpDevtoolsHandler();
|
return NoOpDevtoolsHandler();
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,7 @@ import 'run_cold.dart';
|
|||||||
import 'run_hot.dart';
|
import 'run_hot.dart';
|
||||||
import 'sksl_writer.dart';
|
import 'sksl_writer.dart';
|
||||||
import 'vmservice.dart';
|
import 'vmservice.dart';
|
||||||
|
import 'web/chrome.dart';
|
||||||
|
|
||||||
class FlutterDevice {
|
class FlutterDevice {
|
||||||
FlutterDevice(
|
FlutterDevice(
|
||||||
@ -1048,7 +1049,19 @@ abstract class ResidentRunner extends ResidentHandlers {
|
|||||||
artifactDirectory.createSync(recursive: true);
|
artifactDirectory.createSync(recursive: true);
|
||||||
}
|
}
|
||||||
// TODO(bkonyi): remove when ready to serve DevTools from DDS.
|
// TODO(bkonyi): remove when ready to serve DevTools from DDS.
|
||||||
_residentDevtoolsHandler = devtoolsHandler(DevtoolsLauncher.instance, this, globals.logger);
|
_residentDevtoolsHandler = devtoolsHandler(
|
||||||
|
DevtoolsLauncher.instance,
|
||||||
|
this,
|
||||||
|
globals.logger,
|
||||||
|
ChromiumLauncher(
|
||||||
|
fileSystem: globals.fs,
|
||||||
|
platform: globals.platform,
|
||||||
|
processManager: globals.processManager,
|
||||||
|
operatingSystemUtils: globals.os,
|
||||||
|
browserFinder: findChromeExecutable,
|
||||||
|
logger: globals.logger,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -12,7 +12,6 @@ dependencies:
|
|||||||
# https://github.com/flutter/flutter/blob/main/docs/infra/Updating-dependencies-in-Flutter.md
|
# https://github.com/flutter/flutter/blob/main/docs/infra/Updating-dependencies-in-Flutter.md
|
||||||
archive: 3.6.1
|
archive: 3.6.1
|
||||||
args: 2.6.0
|
args: 2.6.0
|
||||||
browser_launcher: 1.1.3
|
|
||||||
dds: 5.0.0
|
dds: 5.0.0
|
||||||
dwds: 24.3.2
|
dwds: 24.3.2
|
||||||
completion: 1.0.1
|
completion: 1.0.1
|
||||||
@ -71,6 +70,7 @@ dependencies:
|
|||||||
_fe_analyzer_shared: 76.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
_fe_analyzer_shared: 76.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||||
analyzer: 6.11.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
analyzer: 6.11.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||||
boolean_selector: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
boolean_selector: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||||
|
browser_launcher: 1.1.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||||
built_collection: 5.1.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
built_collection: 5.1.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||||
built_value: 8.9.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
built_value: 8.9.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||||
clock: 1.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
clock: 1.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||||
|
@ -6,6 +6,8 @@ import 'dart:async';
|
|||||||
|
|
||||||
import 'package:flutter_tools/src/artifacts.dart';
|
import 'package:flutter_tools/src/artifacts.dart';
|
||||||
import 'package:flutter_tools/src/base/dds.dart';
|
import 'package:flutter_tools/src/base/dds.dart';
|
||||||
|
import 'package:flutter_tools/src/base/file_system.dart';
|
||||||
|
import 'package:flutter_tools/src/base/io.dart';
|
||||||
import 'package:flutter_tools/src/base/logger.dart';
|
import 'package:flutter_tools/src/base/logger.dart';
|
||||||
import 'package:flutter_tools/src/build_info.dart';
|
import 'package:flutter_tools/src/build_info.dart';
|
||||||
import 'package:flutter_tools/src/cache.dart';
|
import 'package:flutter_tools/src/cache.dart';
|
||||||
@ -14,6 +16,7 @@ import 'package:flutter_tools/src/devtools_launcher.dart';
|
|||||||
import 'package:flutter_tools/src/resident_devtools_handler.dart';
|
import 'package:flutter_tools/src/resident_devtools_handler.dart';
|
||||||
import 'package:flutter_tools/src/resident_runner.dart';
|
import 'package:flutter_tools/src/resident_runner.dart';
|
||||||
import 'package:flutter_tools/src/vmservice.dart';
|
import 'package:flutter_tools/src/vmservice.dart';
|
||||||
|
import 'package:flutter_tools/src/web/chrome.dart';
|
||||||
import 'package:test/fake.dart';
|
import 'package:test/fake.dart';
|
||||||
import 'package:vm_service/vm_service.dart' as vm_service;
|
import 'package:vm_service/vm_service.dart' as vm_service;
|
||||||
import 'package:vm_service/vm_service.dart';
|
import 'package:vm_service/vm_service.dart';
|
||||||
@ -58,6 +61,7 @@ void main() {
|
|||||||
null,
|
null,
|
||||||
FakeResidentRunner(),
|
FakeResidentRunner(),
|
||||||
BufferLogger.test(),
|
BufferLogger.test(),
|
||||||
|
_FakeChromiumLauncher(),
|
||||||
);
|
);
|
||||||
|
|
||||||
await handler.serveAndAnnounceDevTools(flutterDevices: <FlutterDevice>[]);
|
await handler.serveAndAnnounceDevTools(flutterDevices: <FlutterDevice>[]);
|
||||||
@ -72,8 +76,8 @@ void main() {
|
|||||||
FakeDevtoolsLauncher(),
|
FakeDevtoolsLauncher(),
|
||||||
FakeResidentRunner()..supportsServiceProtocol = false,
|
FakeResidentRunner()..supportsServiceProtocol = false,
|
||||||
BufferLogger.test(),
|
BufferLogger.test(),
|
||||||
|
_FakeChromiumLauncher(),
|
||||||
);
|
);
|
||||||
|
|
||||||
await handler.serveAndAnnounceDevTools(flutterDevices: <FlutterDevice>[]);
|
await handler.serveAndAnnounceDevTools(flutterDevices: <FlutterDevice>[]);
|
||||||
|
|
||||||
expect(handler.activeDevToolsServer, null);
|
expect(handler.activeDevToolsServer, null);
|
||||||
@ -94,6 +98,7 @@ void main() {
|
|||||||
launcher,
|
launcher,
|
||||||
FakeResidentRunner(),
|
FakeResidentRunner(),
|
||||||
BufferLogger.test(),
|
BufferLogger.test(),
|
||||||
|
_FakeChromiumLauncher(),
|
||||||
);
|
);
|
||||||
|
|
||||||
await handler.serveAndAnnounceDevTools(
|
await handler.serveAndAnnounceDevTools(
|
||||||
@ -114,6 +119,7 @@ void main() {
|
|||||||
..devToolsUrl = Uri.parse('http://localhost:8080'),
|
..devToolsUrl = Uri.parse('http://localhost:8080'),
|
||||||
FakeResidentRunner(),
|
FakeResidentRunner(),
|
||||||
BufferLogger.test(),
|
BufferLogger.test(),
|
||||||
|
_FakeChromiumLauncher(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// VM Service is intentionally null
|
// VM Service is intentionally null
|
||||||
@ -132,6 +138,7 @@ void main() {
|
|||||||
..devToolsUrl = Uri.parse('http://localhost:8080'),
|
..devToolsUrl = Uri.parse('http://localhost:8080'),
|
||||||
FakeResidentRunner(),
|
FakeResidentRunner(),
|
||||||
BufferLogger.test(),
|
BufferLogger.test(),
|
||||||
|
_FakeChromiumLauncher(),
|
||||||
);
|
);
|
||||||
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(
|
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(
|
||||||
requests: <VmServiceExpectation>[
|
requests: <VmServiceExpectation>[
|
||||||
@ -170,6 +177,7 @@ void main() {
|
|||||||
FakeDevtoolsLauncher()..activeDevToolsServer = null,
|
FakeDevtoolsLauncher()..activeDevToolsServer = null,
|
||||||
FakeResidentRunner(),
|
FakeResidentRunner(),
|
||||||
BufferLogger.test(),
|
BufferLogger.test(),
|
||||||
|
_FakeChromiumLauncher(),
|
||||||
);
|
);
|
||||||
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(
|
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(
|
||||||
requests: <VmServiceExpectation>[],
|
requests: <VmServiceExpectation>[],
|
||||||
@ -188,6 +196,7 @@ void main() {
|
|||||||
..devToolsUrl = Uri.parse('http://localhost:8080'),
|
..devToolsUrl = Uri.parse('http://localhost:8080'),
|
||||||
FakeResidentRunner(),
|
FakeResidentRunner(),
|
||||||
BufferLogger.test(),
|
BufferLogger.test(),
|
||||||
|
_FakeChromiumLauncher(),
|
||||||
);
|
);
|
||||||
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(
|
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(
|
||||||
requests: <VmServiceExpectation>[
|
requests: <VmServiceExpectation>[
|
||||||
@ -228,6 +237,7 @@ void main() {
|
|||||||
FakeDevtoolsLauncher()..activeDevToolsServer = DevToolsServerAddress('localhost', 8080),
|
FakeDevtoolsLauncher()..activeDevToolsServer = DevToolsServerAddress('localhost', 8080),
|
||||||
FakeResidentRunner(),
|
FakeResidentRunner(),
|
||||||
BufferLogger.test(),
|
BufferLogger.test(),
|
||||||
|
_FakeChromiumLauncher(),
|
||||||
);
|
);
|
||||||
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(
|
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(
|
||||||
requests: <VmServiceExpectation>[
|
requests: <VmServiceExpectation>[
|
||||||
@ -258,6 +268,7 @@ void main() {
|
|||||||
..devToolsUrl = Uri.parse('http://localhost:8080'),
|
..devToolsUrl = Uri.parse('http://localhost:8080'),
|
||||||
FakeResidentRunner(),
|
FakeResidentRunner(),
|
||||||
BufferLogger.test(),
|
BufferLogger.test(),
|
||||||
|
_FakeChromiumLauncher(),
|
||||||
);
|
);
|
||||||
|
|
||||||
final FakeVmServiceHost vmServiceHost = FakeVmServiceHost(
|
final FakeVmServiceHost vmServiceHost = FakeVmServiceHost(
|
||||||
@ -314,6 +325,7 @@ void main() {
|
|||||||
null,
|
null,
|
||||||
FakeResidentRunner(),
|
FakeResidentRunner(),
|
||||||
BufferLogger.test(),
|
BufferLogger.test(),
|
||||||
|
_FakeChromiumLauncher(),
|
||||||
);
|
);
|
||||||
|
|
||||||
handler.launchDevToolsInBrowser(flutterDevices: <FlutterDevice>[]);
|
handler.launchDevToolsInBrowser(flutterDevices: <FlutterDevice>[]);
|
||||||
@ -328,6 +340,7 @@ void main() {
|
|||||||
FakeDevtoolsLauncher(),
|
FakeDevtoolsLauncher(),
|
||||||
FakeResidentRunner()..supportsServiceProtocol = false,
|
FakeResidentRunner()..supportsServiceProtocol = false,
|
||||||
BufferLogger.test(),
|
BufferLogger.test(),
|
||||||
|
_FakeChromiumLauncher(),
|
||||||
);
|
);
|
||||||
|
|
||||||
handler.launchDevToolsInBrowser(flutterDevices: <FlutterDevice>[]);
|
handler.launchDevToolsInBrowser(flutterDevices: <FlutterDevice>[]);
|
||||||
@ -349,6 +362,7 @@ void main() {
|
|||||||
..readyCompleter = completer,
|
..readyCompleter = completer,
|
||||||
FakeResidentRunner(),
|
FakeResidentRunner(),
|
||||||
BufferLogger.test(),
|
BufferLogger.test(),
|
||||||
|
_FakeChromiumLauncher(),
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(handler.launchDevToolsInBrowser(flutterDevices: <FlutterDevice>[]), isTrue);
|
expect(handler.launchDevToolsInBrowser(flutterDevices: <FlutterDevice>[]), isTrue);
|
||||||
@ -369,12 +383,27 @@ void main() {
|
|||||||
..activeDevToolsServer = DevToolsServerAddress('localhost', 8080),
|
..activeDevToolsServer = DevToolsServerAddress('localhost', 8080),
|
||||||
FakeResidentRunner(),
|
FakeResidentRunner(),
|
||||||
BufferLogger.test(),
|
BufferLogger.test(),
|
||||||
|
_FakeChromiumLauncher(),
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(handler.launchDevToolsInBrowser(flutterDevices: <FlutterDevice>[]), isTrue);
|
expect(handler.launchDevToolsInBrowser(flutterDevices: <FlutterDevice>[]), isTrue);
|
||||||
expect(handler.launchedInBrowser, isTrue);
|
expect(handler.launchedInBrowser, isTrue);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWithoutContext('launchDevToolsInBrowser fails without Chrome installed', () async {
|
||||||
|
final FlutterResidentDevtoolsHandler handler = FlutterResidentDevtoolsHandler(
|
||||||
|
FakeDevtoolsLauncher()
|
||||||
|
..devToolsUrl = Uri(host: 'localhost', port: 8080)
|
||||||
|
..activeDevToolsServer = DevToolsServerAddress('localhost', 8080),
|
||||||
|
FakeResidentRunner(),
|
||||||
|
BufferLogger.test(),
|
||||||
|
_ThrowingChromiumLauncher(),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(handler.launchedInBrowser, isFalse);
|
||||||
|
expect(handler.launchDevToolsInBrowser(flutterDevices: <FlutterDevice>[]), isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
testWithoutContext(
|
testWithoutContext(
|
||||||
'Converts a VM Service URI with a query parameter to a pretty display string',
|
'Converts a VM Service URI with a query parameter to a pretty display string',
|
||||||
() {
|
() {
|
||||||
@ -443,3 +472,19 @@ class FakeDartDevelopmentService extends Fake implements DartDevelopmentService
|
|||||||
disposed = true;
|
disposed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _ThrowingChromiumLauncher extends Fake implements ChromiumLauncher {
|
||||||
|
@override
|
||||||
|
Future<Chromium> launch(
|
||||||
|
String url, {
|
||||||
|
bool headless = false,
|
||||||
|
int? debugPort,
|
||||||
|
bool skipCheck = false,
|
||||||
|
Directory? cacheDir,
|
||||||
|
List<String> webBrowserFlags = const <String>[],
|
||||||
|
}) async {
|
||||||
|
throw ProcessException('ChromiumLauncher', <String>[url]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _FakeChromiumLauncher extends Fake implements ChromiumLauncher {}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user