
Revert "fix devicelab manfiest (#33698)" This reverts commit 5a6a00dc54cb9c5f6865fd31f930ca5665a0e4af. This reverts commit 0d79f0fc79f1ab46f80a3d8d734fdadccea1fb4a.
247 lines
7.3 KiB
Dart
247 lines
7.3 KiB
Dart
// Copyright 2019 The Chromium 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 '../application_package.dart';
|
|
import '../asset.dart';
|
|
import '../base/common.dart';
|
|
import '../base/context.dart';
|
|
import '../base/file_system.dart';
|
|
import '../base/io.dart';
|
|
import '../base/logger.dart';
|
|
import '../base/platform.dart';
|
|
import '../base/process_manager.dart';
|
|
import '../build_info.dart';
|
|
import '../bundle.dart';
|
|
import '../device.dart';
|
|
import '../globals.dart';
|
|
import '../project.dart';
|
|
import '../version.dart';
|
|
import '../web/compile.dart';
|
|
|
|
ChromeLauncher get chromeLauncher => context.get<ChromeLauncher>();
|
|
|
|
/// Only launch or display web devices if `FLUTTER_WEB`
|
|
/// environment variable is set to true.
|
|
bool get flutterWebEnabled {
|
|
_flutterWebEnabled = platform.environment['FLUTTER_WEB']?.toLowerCase() == 'true';
|
|
return _flutterWebEnabled && !FlutterVersion.instance.isStable;
|
|
}
|
|
bool _flutterWebEnabled;
|
|
|
|
|
|
class WebApplicationPackage extends ApplicationPackage {
|
|
WebApplicationPackage(this._flutterProject) : super(id: _flutterProject.manifest.appName);
|
|
|
|
final FlutterProject _flutterProject;
|
|
|
|
@override
|
|
String get name => _flutterProject.manifest.appName;
|
|
|
|
/// The location of the web source assets.
|
|
Directory get webSourcePath => _flutterProject.directory.childDirectory('web');
|
|
}
|
|
|
|
|
|
class WebDevice extends Device {
|
|
WebDevice() : super('web');
|
|
|
|
HttpServer _server;
|
|
WebApplicationPackage _package;
|
|
|
|
@override
|
|
bool get supportsHotReload => true;
|
|
|
|
@override
|
|
bool get supportsHotRestart => true;
|
|
|
|
@override
|
|
bool get supportsStartPaused => true;
|
|
|
|
@override
|
|
bool get supportsStopApp => true;
|
|
|
|
@override
|
|
bool get supportsScreenshot => false;
|
|
|
|
@override
|
|
void clearLogs() { }
|
|
|
|
@override
|
|
DeviceLogReader getLogReader({ApplicationPackage app}) {
|
|
return NoOpDeviceLogReader(app.name);
|
|
}
|
|
|
|
@override
|
|
Future<bool> installApp(ApplicationPackage app) async => true;
|
|
|
|
@override
|
|
Future<bool> isAppInstalled(ApplicationPackage app) async => true;
|
|
|
|
@override
|
|
Future<bool> isLatestBuildInstalled(ApplicationPackage app) async => true;
|
|
|
|
@override
|
|
Future<bool> get isLocalEmulator async => false;
|
|
|
|
@override
|
|
bool isSupported() => flutterWebEnabled;
|
|
|
|
@override
|
|
String get name => 'web';
|
|
|
|
@override
|
|
DevicePortForwarder get portForwarder => const NoOpDevicePortForwarder();
|
|
|
|
@override
|
|
Future<String> get sdkNameAndVersion async => 'web';
|
|
|
|
@override
|
|
Future<LaunchResult> startApp(
|
|
covariant WebApplicationPackage package, {
|
|
String mainPath,
|
|
String route,
|
|
DebuggingOptions debuggingOptions,
|
|
Map<String, Object> platformArgs,
|
|
bool prebuiltApplication = false,
|
|
bool usesTerminalUi = true,
|
|
bool ipv6 = false,
|
|
}) async {
|
|
final Status status = logger.startProgress('Compiling ${package.name} to JavaScript...', timeout: null);
|
|
final int result = await webCompiler.compileDart2js(target: mainPath, minify: false, enabledAssertions: true);
|
|
status.stop();
|
|
if (result != 0) {
|
|
printError('Failed to compile ${package.name} to JavaScript');
|
|
return LaunchResult.failed();
|
|
}
|
|
final AssetBundle assetBundle = AssetBundleFactory.instance.createBundle();
|
|
final int build = await assetBundle.build();
|
|
if (build != 0) {
|
|
throwToolExit('Error: Failed to build asset bundle');
|
|
}
|
|
await writeBundle(fs.directory(getAssetBuildDirectory()), assetBundle.entries);
|
|
|
|
_package = package;
|
|
_server = await HttpServer.bind(InternetAddress.loopbackIPv4, 0);
|
|
_server.listen(_basicAssetServer);
|
|
printStatus('Serving assets from http:localhost:${_server.port}');
|
|
await chromeLauncher.launch('http://localhost:${_server.port}');
|
|
return LaunchResult.succeeded(observatoryUri: null);
|
|
}
|
|
|
|
// Note: we don't currently have a way to track which chrome processes
|
|
// belong to the flutter tool, so we'll err on the side of caution by
|
|
// keeping these open.
|
|
@override
|
|
Future<bool> stopApp(ApplicationPackage app) async {
|
|
await _server?.close();
|
|
_server = null;
|
|
return true;
|
|
}
|
|
|
|
@override
|
|
Future<TargetPlatform> get targetPlatform async => TargetPlatform.web;
|
|
|
|
@override
|
|
Future<bool> uninstallApp(ApplicationPackage app) async => true;
|
|
|
|
Future<void> _basicAssetServer(HttpRequest request) async {
|
|
if (request.method != 'GET') {
|
|
request.response.statusCode = HttpStatus.forbidden;
|
|
await request.response.close();
|
|
return;
|
|
}
|
|
// Resolve all get requests to the build/web/ or build/flutter_assets directory.
|
|
final Uri uri = request.uri;
|
|
File file;
|
|
String contentType;
|
|
if (uri.path == '/') {
|
|
file = _package.webSourcePath.childFile('index.html');
|
|
contentType = 'text/html';
|
|
} else if (uri.path == '/main.dart.js') {
|
|
file = fs.file(fs.path.join(getWebBuildDirectory(), 'main.dart.js'));
|
|
contentType = 'text/javascript';
|
|
} else {
|
|
file = fs.file(fs.path.join(getAssetBuildDirectory(), uri.path.replaceFirst('/assets/', '')));
|
|
}
|
|
|
|
if (!file.existsSync()) {
|
|
request.response.statusCode = HttpStatus.notFound;
|
|
await request.response.close();
|
|
return;
|
|
}
|
|
request.response.statusCode = HttpStatus.ok;
|
|
if (contentType != null) {
|
|
request.response.headers.add(HttpHeaders.contentTypeHeader, contentType);
|
|
}
|
|
await request.response.addStream(file.openRead());
|
|
await request.response.close();
|
|
}
|
|
|
|
@override
|
|
bool isSupportedForProject(FlutterProject flutterProject) {
|
|
return flutterProject.web.existsSync();
|
|
}
|
|
}
|
|
|
|
class WebDevices extends PollingDeviceDiscovery {
|
|
WebDevices() : super('web');
|
|
|
|
final WebDevice _webDevice = WebDevice();
|
|
|
|
@override
|
|
bool get canListAnything => flutterWebEnabled;
|
|
|
|
@override
|
|
Future<List<Device>> pollingGetDevices() async {
|
|
return <Device>[
|
|
_webDevice,
|
|
];
|
|
}
|
|
|
|
@override
|
|
bool get supportsPlatform => flutterWebEnabled;
|
|
}
|
|
|
|
const String _klinuxExecutable = 'google-chrome';
|
|
const String _kMacOSExecutable = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome';
|
|
const String _kWindowsExecutable = r'Google\Chrome\Application\chrome.exe';
|
|
final List<String> _kWindowsPrefixes = <String>[
|
|
platform.environment['LOCALAPPDATA'],
|
|
platform.environment['PROGRAMFILES'],
|
|
platform.environment['PROGRAMFILES(X86)'],
|
|
];
|
|
|
|
// Responsible for launching chrome with devtools configured.
|
|
class ChromeLauncher {
|
|
const ChromeLauncher();
|
|
|
|
/// Launch the chrome browser to a particular `host` page.
|
|
Future<Process> launch(String host) async {
|
|
String executable;
|
|
if (platform.isMacOS) {
|
|
executable = _kMacOSExecutable;
|
|
} else if (platform.isLinux) {
|
|
executable = _klinuxExecutable;
|
|
} else if (platform.isWindows) {
|
|
final String filePath = _kWindowsPrefixes.firstWhere((String prefix) {
|
|
if (prefix == null) {
|
|
return false;
|
|
}
|
|
final String path = fs.path.join(prefix, _kWindowsExecutable);
|
|
return fs.file(path).existsSync();
|
|
}, orElse: () => '.');
|
|
executable = filePath;
|
|
} else {
|
|
throwToolExit('Platform ${platform.operatingSystem} is not supported.');
|
|
}
|
|
if (!fs.file(executable).existsSync()) {
|
|
throwToolExit('Chrome executable not found at $executable');
|
|
}
|
|
return processManager.start(<String>[
|
|
executable,
|
|
host,
|
|
], mode: ProcessStartMode.detached);
|
|
}
|
|
}
|