mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
fix: prevent duplicate Chrome launch in flutter drive
flutter drive -d chrome was opening Chrome twice - once from WebDriver and once from web_device.dart. Added webNoLaunchChrome flag to DebuggingOptions so we can skip the second launch.
This commit is contained in:
parent
b3993b944e
commit
2fae58b08f
@ -332,9 +332,11 @@ class DriveCommand extends RunCommandBase {
|
||||
);
|
||||
final DriverService driverService = _flutterDriverFactory!.createDriverService(web);
|
||||
final BuildInfo buildInfo = await getBuildInfo();
|
||||
final bool isWebDevice = device is ChromiumDevice || device is WebServerDevice;
|
||||
final DebuggingOptions debuggingOptions = await createDebuggingOptions(
|
||||
webDevServerConfig: webDevServerConfig,
|
||||
webChromeBinary: stringArg('chrome-binary'),
|
||||
webNoLaunchChrome: isWebDevice,
|
||||
);
|
||||
final File? applicationBinary = applicationBinaryPath == null
|
||||
? null
|
||||
@ -353,7 +355,6 @@ class DriveCommand extends RunCommandBase {
|
||||
mainPath: targetFile,
|
||||
platformArgs: <String, Object>{
|
||||
if (traceStartup) 'trace-startup': traceStartup,
|
||||
if (web) '--no-launch-chrome': true,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
|
||||
@ -285,6 +285,7 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
|
||||
Future<DebuggingOptions> createDebuggingOptions({
|
||||
WebDevServerConfig? webDevServerConfig,
|
||||
String? webChromeBinary,
|
||||
bool webNoLaunchChrome = false,
|
||||
}) async {
|
||||
final BuildInfo buildInfo = await getBuildInfo();
|
||||
final int? webBrowserDebugPort =
|
||||
@ -315,6 +316,7 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
|
||||
webBrowserFlags: webBrowserFlags,
|
||||
webCrossOriginIsolation: webCrossOriginIsolation,
|
||||
webChromeBinary: webChromeBinary,
|
||||
webNoLaunchChrome: webNoLaunchChrome,
|
||||
webRenderer: webRenderer,
|
||||
webUseWasm: useWasm,
|
||||
enableImpeller: enableImpeller,
|
||||
@ -369,6 +371,7 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
|
||||
webBrowserDebugPort: webBrowserDebugPort,
|
||||
webBrowserFlags: webBrowserFlags,
|
||||
webChromeBinary: webChromeBinary,
|
||||
webNoLaunchChrome: webNoLaunchChrome,
|
||||
webEnableExpressionEvaluation:
|
||||
featureFlags.isWebEnabled && boolArg('web-enable-expression-evaluation'),
|
||||
webLaunchUrl: featureFlags.isWebEnabled ? stringArg('web-launch-url') : null,
|
||||
|
||||
@ -986,6 +986,7 @@ class DebuggingOptions {
|
||||
this.webBrowserDebugPort,
|
||||
this.webBrowserFlags = const <String>[],
|
||||
this.webChromeBinary,
|
||||
this.webNoLaunchChrome = false,
|
||||
this.webEnableExpressionEvaluation = false,
|
||||
this.webLaunchUrl,
|
||||
bool? webCrossOriginIsolation,
|
||||
@ -1022,6 +1023,7 @@ class DebuggingOptions {
|
||||
this.webBrowserDebugPort,
|
||||
this.webBrowserFlags = const <String>[],
|
||||
this.webChromeBinary,
|
||||
this.webNoLaunchChrome = false,
|
||||
this.webLaunchUrl,
|
||||
bool? webCrossOriginIsolation,
|
||||
WebRendererMode? webRenderer,
|
||||
@ -1103,6 +1105,7 @@ class DebuggingOptions {
|
||||
required this.webBrowserDebugPort,
|
||||
required this.webBrowserFlags,
|
||||
required this.webChromeBinary,
|
||||
required this.webNoLaunchChrome,
|
||||
required this.webEnableExpressionEvaluation,
|
||||
required this.webLaunchUrl,
|
||||
required this.webCrossOriginIsolation,
|
||||
@ -1191,6 +1194,12 @@ class DebuggingOptions {
|
||||
/// Custom path to the Chrome executable.
|
||||
final String? webChromeBinary;
|
||||
|
||||
/// Whether to skip launching Chrome when running web apps.
|
||||
///
|
||||
/// This is used by `flutter drive` to prevent launching a second Chrome
|
||||
/// instance since the driver service launches Chrome separately.
|
||||
final bool webNoLaunchChrome;
|
||||
|
||||
/// Enable expression evaluation for web target.
|
||||
final bool webEnableExpressionEvaluation;
|
||||
|
||||
@ -1301,6 +1310,7 @@ class DebuggingOptions {
|
||||
'webBrowserDebugPort': webBrowserDebugPort,
|
||||
'webBrowserFlags': webBrowserFlags,
|
||||
'webChromeBinary': webChromeBinary,
|
||||
'webNoLaunchChrome': webNoLaunchChrome,
|
||||
'webEnableExpressionEvaluation': webEnableExpressionEvaluation,
|
||||
'webLaunchUrl': webLaunchUrl,
|
||||
'webCrossOriginIsolation': webCrossOriginIsolation,
|
||||
@ -1370,6 +1380,7 @@ class DebuggingOptions {
|
||||
webBrowserDebugPort: json['webBrowserDebugPort'] as int?,
|
||||
webBrowserFlags: (json['webBrowserFlags']! as List<dynamic>).cast<String>(),
|
||||
webChromeBinary: json['webChromeBinary'] as String?,
|
||||
webNoLaunchChrome: (json['webNoLaunchChrome'] as bool?) ?? false,
|
||||
webEnableExpressionEvaluation: json['webEnableExpressionEvaluation']! as bool,
|
||||
webLaunchUrl: json['webLaunchUrl'] as String?,
|
||||
webCrossOriginIsolation: json['webCrossOriginIsolation']! as bool,
|
||||
|
||||
@ -87,6 +87,7 @@ class WebDriverService extends DriverService {
|
||||
buildInfo,
|
||||
webDevServerConfig: debuggingOptions.webDevServerConfig,
|
||||
webChromeBinary: debuggingOptions.webChromeBinary,
|
||||
webNoLaunchChrome: debuggingOptions.webNoLaunchChrome,
|
||||
webRenderer: debuggingOptions.webRenderer,
|
||||
webUseWasm: debuggingOptions.webUseWasm,
|
||||
)
|
||||
@ -94,6 +95,7 @@ class WebDriverService extends DriverService {
|
||||
buildInfo,
|
||||
webDevServerConfig: debuggingOptions.webDevServerConfig,
|
||||
webChromeBinary: debuggingOptions.webChromeBinary,
|
||||
webNoLaunchChrome: debuggingOptions.webNoLaunchChrome,
|
||||
disablePortPublication: debuggingOptions.disablePortPublication,
|
||||
webRenderer: debuggingOptions.webRenderer,
|
||||
webUseWasm: debuggingOptions.webUseWasm,
|
||||
|
||||
@ -135,8 +135,7 @@ abstract class ChromiumDevice extends WebDevice {
|
||||
} else {
|
||||
url = platformArgs['uri']! as String;
|
||||
}
|
||||
final launchChrome = platformArgs['no-launch-chrome'] != true;
|
||||
if (launchChrome) {
|
||||
if (!debuggingOptions.webNoLaunchChrome) {
|
||||
_chrome = await chromeLauncher.launch(
|
||||
url,
|
||||
cacheDir: _fileSystem.currentDirectory
|
||||
@ -148,7 +147,7 @@ abstract class ChromiumDevice extends WebDevice {
|
||||
chromeBinary: debuggingOptions.webChromeBinary,
|
||||
);
|
||||
}
|
||||
_logger.sendEvent('app.webLaunchUrl', <String, Object>{'url': url, 'launched': launchChrome});
|
||||
_logger.sendEvent('app.webLaunchUrl', <String, Object>{'url': url, 'launched': !debuggingOptions.webNoLaunchChrome});
|
||||
return LaunchResult.succeeded(vmServiceUri: Uri.parse(url));
|
||||
}
|
||||
|
||||
|
||||
@ -58,6 +58,52 @@ void main() {
|
||||
},
|
||||
);
|
||||
|
||||
testWithoutContext(
|
||||
'ChromiumDevice.startApp does not launch Chrome when webNoLaunchChrome is true',
|
||||
() async {
|
||||
final launcher = _TrackingChromiumLauncher();
|
||||
final chromiumDevice = _FakeChromiumDevice(
|
||||
chromiumLauncher: launcher,
|
||||
fileSystem: MemoryFileSystem.test(),
|
||||
logger: BufferLogger.test(),
|
||||
);
|
||||
|
||||
await chromiumDevice.startApp(
|
||||
null,
|
||||
debuggingOptions: DebuggingOptions.enabled(
|
||||
BuildInfo.debug,
|
||||
webNoLaunchChrome: true,
|
||||
),
|
||||
platformArgs: <String, Object?>{'uri': 'http://localhost:8080'},
|
||||
);
|
||||
|
||||
expect(launcher.launchCalled, isFalse);
|
||||
},
|
||||
);
|
||||
|
||||
testWithoutContext(
|
||||
'ChromiumDevice.startApp launches Chrome when webNoLaunchChrome is false',
|
||||
() async {
|
||||
final launcher = _TrackingChromiumLauncher();
|
||||
final chromiumDevice = _FakeChromiumDevice(
|
||||
chromiumLauncher: launcher,
|
||||
fileSystem: MemoryFileSystem.test(),
|
||||
logger: BufferLogger.test(),
|
||||
);
|
||||
|
||||
await chromiumDevice.startApp(
|
||||
null,
|
||||
debuggingOptions: DebuggingOptions.enabled(
|
||||
BuildInfo.debug,
|
||||
webNoLaunchChrome: false,
|
||||
),
|
||||
platformArgs: <String, Object?>{'uri': 'http://localhost:8080'},
|
||||
);
|
||||
|
||||
expect(launcher.launchCalled, isTrue);
|
||||
},
|
||||
);
|
||||
|
||||
testWithoutContext('GoogleChromeDevice defaults', () async {
|
||||
final launcher = TestChromiumLauncher();
|
||||
|
||||
@ -495,3 +541,44 @@ class _OnceClosableChromium extends Fake implements Chromium {
|
||||
}
|
||||
|
||||
class _UnimplementedChromium extends Fake implements Chromium {}
|
||||
|
||||
/// A test implementation of [ChromiumLauncher] that tracks whether launch() was called.
|
||||
class _TrackingChromiumLauncher implements ChromiumLauncher {
|
||||
bool launchCalled = false;
|
||||
|
||||
@override
|
||||
Completer<Chromium> currentCompleter = Completer<Chromium>();
|
||||
|
||||
@override
|
||||
bool canFindExecutable() => true;
|
||||
|
||||
@override
|
||||
Future<Chromium> get connectedInstance => currentCompleter.future;
|
||||
|
||||
@override
|
||||
String findExecutable() => 'chrome';
|
||||
|
||||
@override
|
||||
bool get hasChromeInstance => false;
|
||||
|
||||
@override
|
||||
Future<Chromium> launch(
|
||||
String url, {
|
||||
bool headless = false,
|
||||
int? debugPort,
|
||||
bool skipCheck = false,
|
||||
Directory? cacheDir,
|
||||
List<String> webBrowserFlags = const <String>[],
|
||||
String? chromeBinary,
|
||||
}) async {
|
||||
launchCalled = true;
|
||||
final chromium = _UnimplementedChromium();
|
||||
currentCompleter.complete(chromium);
|
||||
return chromium;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Chromium> connect(Chromium chrome, bool skipCheck) {
|
||||
return currentCompleter.future;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user