mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Merge 2fae58b08f4e0b1ef1e4e6299d4f1a496804f129 into 06df71c51446e96939c6a615b7c34ce9123806ba
This commit is contained in:
commit
78011d9502
@ -332,8 +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
|
||||
@ -352,7 +355,6 @@ class DriveCommand extends RunCommandBase {
|
||||
mainPath: targetFile,
|
||||
platformArgs: <String, Object>{
|
||||
if (traceStartup) 'trace-startup': traceStartup,
|
||||
if (web) '--no-launch-chrome': true,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
|
||||
@ -289,7 +289,11 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
|
||||
/// Create a debugging options instance for the current `run` or `drive` invocation.
|
||||
@visibleForTesting
|
||||
@protected
|
||||
Future<DebuggingOptions> createDebuggingOptions({WebDevServerConfig? webDevServerConfig}) async {
|
||||
Future<DebuggingOptions> createDebuggingOptions({
|
||||
WebDevServerConfig? webDevServerConfig,
|
||||
String? webChromeBinary,
|
||||
bool webNoLaunchChrome = false,
|
||||
}) async {
|
||||
final BuildInfo buildInfo = await getBuildInfo();
|
||||
final int? webBrowserDebugPort =
|
||||
featureFlags.isWebEnabled && argResults!.wasParsed('web-browser-debug-port')
|
||||
@ -318,6 +322,8 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
|
||||
webBrowserDebugPort: webBrowserDebugPort,
|
||||
webBrowserFlags: webBrowserFlags,
|
||||
webCrossOriginIsolation: webCrossOriginIsolation,
|
||||
webChromeBinary: webChromeBinary,
|
||||
webNoLaunchChrome: webNoLaunchChrome,
|
||||
webRenderer: webRenderer,
|
||||
webUseWasm: useWasm,
|
||||
enableImpeller: enableImpeller,
|
||||
@ -372,6 +378,8 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
|
||||
webRunHeadless: featureFlags.isWebEnabled && boolArg('web-run-headless'),
|
||||
webBrowserDebugPort: webBrowserDebugPort,
|
||||
webBrowserFlags: webBrowserFlags,
|
||||
webChromeBinary: webChromeBinary,
|
||||
webNoLaunchChrome: webNoLaunchChrome,
|
||||
webEnableExpressionEvaluation:
|
||||
featureFlags.isWebEnabled && boolArg('web-enable-expression-evaluation'),
|
||||
webLaunchUrl: featureFlags.isWebEnabled ? stringArg('web-launch-url') : null,
|
||||
|
||||
@ -971,6 +971,8 @@ class DebuggingOptions {
|
||||
this.webRunHeadless = false,
|
||||
this.webBrowserDebugPort,
|
||||
this.webBrowserFlags = const <String>[],
|
||||
this.webChromeBinary,
|
||||
this.webNoLaunchChrome = false,
|
||||
this.webEnableExpressionEvaluation = false,
|
||||
this.webLaunchUrl,
|
||||
bool? webCrossOriginIsolation,
|
||||
@ -1007,6 +1009,8 @@ class DebuggingOptions {
|
||||
this.webRunHeadless = false,
|
||||
this.webBrowserDebugPort,
|
||||
this.webBrowserFlags = const <String>[],
|
||||
this.webChromeBinary,
|
||||
this.webNoLaunchChrome = false,
|
||||
this.webLaunchUrl,
|
||||
bool? webCrossOriginIsolation,
|
||||
WebRendererMode? webRenderer,
|
||||
@ -1088,6 +1092,8 @@ class DebuggingOptions {
|
||||
required this.webRunHeadless,
|
||||
required this.webBrowserDebugPort,
|
||||
required this.webBrowserFlags,
|
||||
required this.webChromeBinary,
|
||||
required this.webNoLaunchChrome,
|
||||
required this.webEnableExpressionEvaluation,
|
||||
required this.webLaunchUrl,
|
||||
required this.webCrossOriginIsolation,
|
||||
@ -1175,6 +1181,15 @@ class DebuggingOptions {
|
||||
/// Arbitrary browser flags.
|
||||
final List<String> webBrowserFlags;
|
||||
|
||||
/// 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;
|
||||
|
||||
@ -1284,6 +1299,8 @@ class DebuggingOptions {
|
||||
'webRunHeadless': webRunHeadless,
|
||||
'webBrowserDebugPort': webBrowserDebugPort,
|
||||
'webBrowserFlags': webBrowserFlags,
|
||||
'webChromeBinary': webChromeBinary,
|
||||
'webNoLaunchChrome': webNoLaunchChrome,
|
||||
'webEnableExpressionEvaluation': webEnableExpressionEvaluation,
|
||||
'webLaunchUrl': webLaunchUrl,
|
||||
'webCrossOriginIsolation': webCrossOriginIsolation,
|
||||
@ -1353,6 +1370,8 @@ class DebuggingOptions {
|
||||
webRunHeadless: json['webRunHeadless']! as bool,
|
||||
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,
|
||||
|
||||
@ -86,12 +86,16 @@ class WebDriverService extends DriverService {
|
||||
? DebuggingOptions.disabled(
|
||||
buildInfo,
|
||||
webDevServerConfig: debuggingOptions.webDevServerConfig,
|
||||
webChromeBinary: debuggingOptions.webChromeBinary,
|
||||
webNoLaunchChrome: debuggingOptions.webNoLaunchChrome,
|
||||
webRenderer: debuggingOptions.webRenderer,
|
||||
webUseWasm: debuggingOptions.webUseWasm,
|
||||
)
|
||||
: DebuggingOptions.enabled(
|
||||
buildInfo,
|
||||
webDevServerConfig: debuggingOptions.webDevServerConfig,
|
||||
webChromeBinary: debuggingOptions.webChromeBinary,
|
||||
webNoLaunchChrome: debuggingOptions.webNoLaunchChrome,
|
||||
disablePortPublication: debuggingOptions.disablePortPublication,
|
||||
webRenderer: debuggingOptions.webRenderer,
|
||||
webUseWasm: debuggingOptions.webUseWasm,
|
||||
|
||||
@ -189,6 +189,7 @@ class ChromiumLauncher {
|
||||
bool skipCheck = false,
|
||||
Directory? cacheDir,
|
||||
List<String> webBrowserFlags = const <String>[],
|
||||
String? chromeBinary,
|
||||
}) async {
|
||||
if (currentCompleter.isCompleted) {
|
||||
throwToolExit('Only one instance of chrome can be started.');
|
||||
@ -200,7 +201,7 @@ class ChromiumLauncher {
|
||||
);
|
||||
}
|
||||
|
||||
final String chromeExecutable = _browserFinder(_platform, _fileSystem);
|
||||
final String chromeExecutable = chromeBinary ?? _browserFinder(_platform, _fileSystem);
|
||||
|
||||
if (_logger.isVerbose) {
|
||||
_logger.printTrace('Will use Chromium executable at $chromeExecutable');
|
||||
|
||||
@ -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
|
||||
@ -145,9 +144,10 @@ abstract class ChromiumDevice extends WebDevice {
|
||||
headless: debuggingOptions.webRunHeadless,
|
||||
debugPort: debuggingOptions.webBrowserDebugPort,
|
||||
webBrowserFlags: debuggingOptions.webBrowserFlags,
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
@ -2265,6 +2265,7 @@ class TestChromiumLauncher implements ChromiumLauncher {
|
||||
bool skipCheck = false,
|
||||
Directory? cacheDir,
|
||||
List<String> webBrowserFlags = const <String>[],
|
||||
String? chromeBinary,
|
||||
}) async {
|
||||
return currentCompleter.future;
|
||||
}
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -456,6 +502,7 @@ class TestChromiumLauncher implements ChromiumLauncher {
|
||||
bool skipCheck = false,
|
||||
Directory? cacheDir,
|
||||
List<String> webBrowserFlags = const <String>[],
|
||||
String? chromeBinary,
|
||||
}) async {
|
||||
currentCompleter.complete(_launcher());
|
||||
return currentCompleter.future;
|
||||
@ -494,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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -527,6 +527,29 @@ void main() {
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('can launch chrome with custom binary path', () async {
|
||||
processManager.addCommand(
|
||||
const FakeCommand(
|
||||
command: <String>[
|
||||
'/custom/path/to/chrome',
|
||||
'--user-data-dir=/.tmp_rand0/flutter_tools_chrome_device.rand0',
|
||||
'--remote-debugging-port=12345',
|
||||
...kChromeArgs,
|
||||
'example_url',
|
||||
],
|
||||
stderr: kDevtoolsStderr,
|
||||
),
|
||||
);
|
||||
|
||||
await expectReturnsNormallyLater(
|
||||
chromeLauncher.launch(
|
||||
'example_url',
|
||||
skipCheck: true,
|
||||
chromeBinary: '/custom/path/to/chrome',
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('can launch chrome headless', () async {
|
||||
processManager.addCommand(
|
||||
const FakeCommand(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user