mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
112 lines
3.4 KiB
Dart
112 lines
3.4 KiB
Dart
// Copyright 2014 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
|
|
|
|
import 'dart:async';
|
|
|
|
import 'package:meta/meta.dart';
|
|
import 'package:process/process.dart';
|
|
|
|
import 'base/bot_detector.dart';
|
|
import 'base/common.dart';
|
|
import 'base/io.dart' as io;
|
|
import 'base/logger.dart';
|
|
import 'convert.dart';
|
|
import 'resident_runner.dart';
|
|
|
|
/// An implementation of the devtools launcher that uses `pub global activate` to
|
|
/// start a server instance.
|
|
class DevtoolsServerLauncher extends DevtoolsLauncher {
|
|
DevtoolsServerLauncher({
|
|
required ProcessManager processManager,
|
|
required String dartExecutable,
|
|
required Logger logger,
|
|
required BotDetector botDetector,
|
|
}) : _processManager = processManager,
|
|
_dartExecutable = dartExecutable,
|
|
_logger = logger,
|
|
_botDetector = botDetector;
|
|
|
|
final ProcessManager _processManager;
|
|
final String _dartExecutable;
|
|
final Logger _logger;
|
|
final BotDetector _botDetector;
|
|
final Completer<void> _processStartCompleter = Completer<void>();
|
|
|
|
io.Process? _devToolsProcess;
|
|
bool _devToolsProcessKilled = false;
|
|
@visibleForTesting
|
|
Future<void>? devToolsProcessExit;
|
|
|
|
static final RegExp _serveDevToolsPattern =
|
|
RegExp(r'Serving DevTools at ((http|//)[a-zA-Z0-9:/=_\-\.\[\]]+?)\.?$');
|
|
|
|
@override
|
|
Future<void> get processStart => _processStartCompleter.future;
|
|
|
|
@override
|
|
Future<void> launch(Uri? vmServiceUri, {List<String>? additionalArguments}) async {
|
|
// Place this entire method in a try/catch that swallows exceptions because
|
|
// this method is guaranteed not to return a Future that throws.
|
|
try {
|
|
_devToolsProcess = await _processManager.start(<String>[
|
|
_dartExecutable,
|
|
'devtools',
|
|
'--no-launch-browser',
|
|
if (vmServiceUri != null) '--vm-uri=$vmServiceUri',
|
|
...?additionalArguments,
|
|
]);
|
|
_processStartCompleter.complete();
|
|
final Completer<Uri> completer = Completer<Uri>();
|
|
_devToolsProcess!.stdout
|
|
.transform(utf8.decoder)
|
|
.transform(const LineSplitter())
|
|
.listen((String line) {
|
|
final Match? match = _serveDevToolsPattern.firstMatch(line);
|
|
if (match != null) {
|
|
final String url = match[1]!;
|
|
completer.complete(Uri.parse(url));
|
|
}
|
|
});
|
|
_devToolsProcess!.stderr
|
|
.transform(utf8.decoder)
|
|
.transform(const LineSplitter())
|
|
.listen(_logger.printError);
|
|
|
|
final bool runningOnBot = await _botDetector.isRunningOnBot;
|
|
devToolsProcessExit = _devToolsProcess!.exitCode.then(
|
|
(int exitCode) {
|
|
if (!_devToolsProcessKilled && runningOnBot) {
|
|
throwToolExit('DevTools process failed: exitCode=$exitCode');
|
|
}
|
|
}
|
|
);
|
|
|
|
devToolsUrl = await completer.future;
|
|
} on Exception catch (e, st) {
|
|
_logger.printError('Failed to launch DevTools: $e', stackTrace: st);
|
|
}
|
|
}
|
|
|
|
@override
|
|
Future<DevToolsServerAddress?> serve() async {
|
|
if (activeDevToolsServer == null) {
|
|
await launch(null);
|
|
}
|
|
return activeDevToolsServer;
|
|
}
|
|
|
|
@override
|
|
Future<void> close() async {
|
|
if (devToolsUrl != null) {
|
|
devToolsUrl = null;
|
|
}
|
|
if (_devToolsProcess != null) {
|
|
_devToolsProcessKilled = true;
|
|
_devToolsProcess!.kill();
|
|
}
|
|
}
|
|
}
|