1// Copyright 2019 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5import 'package:meta/meta.dart'; 6 7import '../application_package.dart'; 8import '../base/file_system.dart'; 9import '../base/io.dart'; 10import '../base/platform.dart'; 11import '../base/process_manager.dart'; 12import '../build_info.dart'; 13import '../device.dart'; 14import '../features.dart'; 15import '../project.dart'; 16import 'chrome.dart'; 17import 'workflow.dart'; 18 19class WebApplicationPackage extends ApplicationPackage { 20 WebApplicationPackage(this.flutterProject) : super(id: flutterProject.manifest.appName); 21 22 final FlutterProject flutterProject; 23 24 @override 25 String get name => flutterProject.manifest.appName; 26 27 /// The location of the web source assets. 28 Directory get webSourcePath => flutterProject.directory.childDirectory('web'); 29} 30 31class ChromeDevice extends Device { 32 ChromeDevice() : super( 33 'chrome', 34 category: Category.web, 35 platformType: PlatformType.web, 36 ephemeral: false, 37 ); 38 39 // TODO(jonahwilliams): this is technically false, but requires some refactoring 40 // to allow hot mode restart only devices. 41 @override 42 bool get supportsHotReload => true; 43 44 @override 45 bool get supportsHotRestart => true; 46 47 @override 48 bool get supportsStartPaused => true; 49 50 @override 51 bool get supportsFlutterExit => true; 52 53 @override 54 bool get supportsScreenshot => false; 55 56 @override 57 void clearLogs() { } 58 59 @override 60 DeviceLogReader getLogReader({ApplicationPackage app}) { 61 return NoOpDeviceLogReader(app.name); 62 } 63 64 @override 65 Future<bool> installApp(ApplicationPackage app) async => true; 66 67 @override 68 Future<bool> isAppInstalled(ApplicationPackage app) async => true; 69 70 @override 71 Future<bool> isLatestBuildInstalled(ApplicationPackage app) async => true; 72 73 @override 74 Future<bool> get isLocalEmulator async => false; 75 76 @override 77 Future<String> get emulatorId async => null; 78 79 @override 80 bool isSupported() => featureFlags.isWebEnabled && canFindChrome(); 81 82 @override 83 String get name => 'Chrome'; 84 85 @override 86 DevicePortForwarder get portForwarder => const NoOpDevicePortForwarder(); 87 88 @override 89 Future<String> get sdkNameAndVersion async { 90 if (!isSupported()) { 91 return 'unknown'; 92 } 93 // See https://bugs.chromium.org/p/chromium/issues/detail?id=158372 94 String version = 'unknown'; 95 if (platform.isWindows) { 96 final ProcessResult result = await processManager.run(<String>[ 97 r'reg', 'query', 'HKEY_CURRENT_USER\\Software\\Google\\Chrome\\BLBeacon', '/v', 'version' 98 ]); 99 if (result.exitCode == 0) { 100 final List<String> parts = result.stdout.split(RegExp(r'\s+')); 101 if (parts.length > 2) { 102 version = 'Google Chrome ' + parts[parts.length - 2]; 103 } 104 } 105 } else { 106 final String chrome = findChromeExecutable(); 107 final ProcessResult result = await processManager.run(<String>[ 108 chrome, 109 '--version', 110 ]); 111 if (result.exitCode == 0) { 112 version = result.stdout; 113 } 114 } 115 return version; 116 } 117 118 @override 119 Future<LaunchResult> startApp( 120 covariant WebApplicationPackage package, { 121 String mainPath, 122 String route, 123 DebuggingOptions debuggingOptions, 124 Map<String, Object> platformArgs, 125 bool prebuiltApplication = false, 126 bool usesTerminalUi = true, 127 bool ipv6 = false, 128 }) async { 129 // See [ResidentWebRunner.run] in flutter_tools/lib/src/resident_web_runner.dart 130 // for the web initialization and server logic. 131 return LaunchResult.succeeded(observatoryUri: null); 132 } 133 134 @override 135 Future<bool> stopApp(ApplicationPackage app) async { 136 return true; 137 } 138 139 @override 140 Future<TargetPlatform> get targetPlatform async => TargetPlatform.web_javascript; 141 142 @override 143 Future<bool> uninstallApp(ApplicationPackage app) async => true; 144 145 @override 146 bool isSupportedForProject(FlutterProject flutterProject) { 147 return flutterProject.web.existsSync(); 148 } 149} 150 151class WebDevices extends PollingDeviceDiscovery { 152 WebDevices() : super('chrome'); 153 154 final ChromeDevice _webDevice = ChromeDevice(); 155 156 @override 157 bool get canListAnything => featureFlags.isWebEnabled; 158 159 @override 160 Future<List<Device>> pollingGetDevices() async { 161 return <Device>[ 162 _webDevice, 163 ]; 164 } 165 166 @override 167 bool get supportsPlatform => featureFlags.isWebEnabled; 168} 169 170@visibleForTesting 171String parseVersionForWindows(String input) { 172 return input.split(RegExp('\w')).last; 173} 174