From 5cbf10febea583a1bbf7a8ceedb95c5d3f1e1bbc Mon Sep 17 00:00:00 2001 From: Ben Konyi Date: Wed, 5 May 2021 20:31:07 +0000 Subject: [PATCH] Revert "[ VM / DDS / CLI ] Add DevTools support to the standalone VM" This reverts commit ef0e4ea10713b546363f24511bfdc2c6ce52d861. Reason for revert: Flutter HHH and golem builds are red. Rolls to Flutter are failing. TEST=N/A Original change's description: > [ VM / DDS / CLI ] Add DevTools support to the standalone VM > > Example output on stdout when DevTools is enabled: > > Observatory listening on http://127.0.0.1:8181/CzkZzZaONW4=/ > The Dart DevTools debugger and profiler is available at: http://127.0.0.1:8181/devtools/#/?uri=ws%3A%2F%2F127.0.0.1%3A8181%2FCzkZzZaONW4%3D%2Fws > hello world! > > vm-service: isolate(1674461414267555) 'main' has no debugger attached and is paused at exit. Connect to Observatory at http://127.0.0.1:8181/CzkZzZaONW4=/ to debug. > > TEST=pkg/dartdev/test/commands/run_test.dart > > Change-Id: Icd1afda87ad4a46f228125d53094d10adf8056ec > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/188361 > Commit-Queue: Ben Konyi > Reviewed-by: Siva Annamalai # Not skipping CQ checks because original CL landed > 1 day ago. Change-Id: I50e8dc4e592e13b44c2fb980b2029d5c5cc3ad2a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/198381 Reviewed-by: Ben Konyi Reviewed-by: Alexander Markov Commit-Queue: Ben Konyi --- .dart_tool/package_config.json | 12 - .packages | 2 - DEPS | 8 +- pkg/dartdev/lib/dartdev.dart | 3 +- pkg/dartdev/lib/src/commands/run.dart | 96 ++----- pkg/dartdev/lib/src/sdk.dart | 7 - pkg/dartdev/test/commands/run_test.dart | 59 ----- pkg/dds/CHANGELOG.md | 3 +- pkg/dds/bin/dds.dart | 33 +-- pkg/dds/lib/dds.dart | 19 -- pkg/dds/lib/src/client.dart | 26 +- pkg/dds/lib/src/constants.dart | 4 - pkg/dds/lib/src/dds_impl.dart | 105 +++----- pkg/dds/lib/src/devtools/devtools_client.dart | 96 ------- .../lib/src/devtools/devtools_handler.dart | 87 ------- pkg/dds/lib/src/devtools/file_system.dart | 84 ------- pkg/dds/lib/src/devtools/server_api.dart | 230 ----------------- pkg/dds/lib/src/devtools/usage.dart | 236 ------------------ pkg/dds/pubspec.yaml | 7 +- runtime/bin/main.cc | 13 +- runtime/bin/main_options.cc | 3 +- sdk/BUILD.gn | 13 - sdk/lib/_internal/vm/bin/vmservice_io.dart | 105 +------- .../_internal/vm/bin/vmservice_server.dart | 8 +- sdk/lib/vmservice/vmservice.dart | 19 +- third_party/devtools/update.sh | 3 +- tools/bots/test_matrix.json | 2 - tools/generate_package_config.dart | 2 - utils/dartdev/BUILD.gn | 14 -- 29 files changed, 108 insertions(+), 1191 deletions(-) delete mode 100644 pkg/dds/lib/src/devtools/devtools_client.dart delete mode 100644 pkg/dds/lib/src/devtools/devtools_handler.dart delete mode 100644 pkg/dds/lib/src/devtools/file_system.dart delete mode 100644 pkg/dds/lib/src/devtools/server_api.dart delete mode 100644 pkg/dds/lib/src/devtools/usage.dart diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json index fa34add9158..6cc4287c1dd 100644 --- a/.dart_tool/package_config.json +++ b/.dart_tool/package_config.json @@ -252,18 +252,6 @@ "packageUri": "lib/", "languageVersion": "2.3" }, - { - "name": "devtools_server", - "rootUri": "../third_party/devtools/devtools_server", - "packageUri": "lib/", - "languageVersion": "2.6" - }, - { - "name": "devtools_shared", - "rootUri": "../third_party/devtools/devtools_shared", - "packageUri": "lib/", - "languageVersion": "2.3" - }, { "name": "diagnostic", "rootUri": "../pkg/diagnostic", diff --git a/.packages b/.packages index 1631e031413..7cbfb8995dc 100644 --- a/.packages +++ b/.packages @@ -21,7 +21,6 @@ bazel_worker:third_party/pkg/bazel_worker/lib benchmark_harness:third_party/pkg/benchmark_harness/lib boolean_selector:third_party/pkg/boolean_selector/lib build_integration:pkg/build_integration/lib -browser_launcher:third_party/pkg/browser_launcher/lib charcode:third_party/pkg/charcode/lib cli_util:third_party/pkg/cli_util/lib collection:third_party/pkg/collection/lib @@ -38,7 +37,6 @@ dartdev:pkg/dartdev/lib dartdoc:third_party/pkg/dartdoc/lib dds:pkg/dds/lib dev_compiler:pkg/dev_compiler/lib -devtools_shared:third_party/devtools/devtools_shared/lib diagnostic:pkg/diagnostic/lib expect:pkg/expect/lib ffi:third_party/pkg/ffi/lib diff --git a/DEPS b/DEPS index 1124ea374b6..ae9b81fb3cb 100644 --- a/DEPS +++ b/DEPS @@ -80,7 +80,6 @@ vars = { "boringssl_gen_rev": "7322fc15cc065d8d2957fccce6b62a509dc4d641", "boringssl_rev" : "1607f54fed72c6589d560254626909a64124f091", "browser-compat-data_tag": "v1.0.22", - "browser_launcher_rev": "12ab9f351a44ac803de9bc17bb2180bb312a9dd7", "charcode_rev": "bcd8a12c315b7a83390e4865ad847ecd9344cba2", "chrome_rev" : "19997", "cli_util_rev" : "50cc840b146615899e97b892578848401b2028d5", @@ -106,6 +105,7 @@ vars = { "dart_style_rev": "f17c23e0eea9a870601c19d904e2a9c1a7c81470", "chromedriver_tag": "83.0.4103.39", + "browser_launcher_rev": "12ab9f351a44ac803de9bc17bb2180bb312a9dd7", "dartdoc_rev" : "505f163f7cb48e917503e4a23fbff1227e08b263", "devtools_rev" : "12ad5341ae0a275042c84a4e7be9a6c98db65612", "jsshell_tag": "version:88.0", @@ -320,9 +320,6 @@ deps = { Var('chromium_git') + '/external/github.com/mdn/browser-compat-data' + "@" + Var("browser-compat-data_tag"), - Var("dart_root") + "/third_party/pkg/browser_launcher": - Var("dart_git") + "browser_launcher.git" + "@" + Var("browser_launcher_rev"), - Var("dart_root") + "/third_party/tcmalloc/gperftools": Var('chromium_git') + '/external/github.com/gperftools/gperftools.git' + "@" + Var("gperftools_revision"), @@ -339,6 +336,9 @@ deps = { Var("dart_root") + "/third_party/pkg/boolean_selector": Var("dart_git") + "boolean_selector.git" + "@" + Var("boolean_selector_rev"), + Var("dart_root") + "/third_party/pkg/browser_launcher": + Var("dart_git") + "browser_launcher.git" + + "@" + Var("browser_launcher_rev"), Var("dart_root") + "/third_party/pkg/charcode": Var("dart_git") + "charcode.git" + "@" + Var("charcode_rev"), Var("dart_root") + "/third_party/pkg/cli_util": diff --git a/pkg/dartdev/lib/dartdev.dart b/pkg/dartdev/lib/dartdev.dart index 5e581c5fda5..b72fbba8c1f 100644 --- a/pkg/dartdev/lib/dartdev.dart +++ b/pkg/dartdev/lib/dartdev.dart @@ -40,8 +40,7 @@ Future runDartdev(List args, SendPort port) async { args = args .where( (element) => !(element.contains('--observe') || - element.contains('--enable-vm-service') || - element.contains('--devtools')), + element.contains('--enable-vm-service')), ) .toList(); } diff --git a/pkg/dartdev/lib/src/commands/run.dart b/pkg/dartdev/lib/src/commands/run.dart index d996c3c8075..db32bfed057 100644 --- a/pkg/dartdev/lib/src/commands/run.dart +++ b/pkg/dartdev/lib/src/commands/run.dart @@ -158,10 +158,6 @@ class RunCommand extends DartdevCommand { hide: !verbose, negatable: false, help: 'Enables tracing of library and script loading.', - ) - ..addFlag( - 'debug-dds', - hide: true, ); addExperimentalFlags(argParser, verbose); } @@ -183,18 +179,13 @@ class RunCommand extends DartdevCommand { String launchDdsArg = argResults['launch-dds']; String ddsHost = ''; String ddsPort = ''; - - // TODO(bkonyi): allow for users to choose not to launch DevTools - // See https://github.com/dart-lang/sdk/issues/45867. - const bool launchDevTools = true; bool launchDds = false; if (launchDdsArg != null) { launchDds = true; - final ddsUrl = launchDdsArg.split('\\:'); + final ddsUrl = launchDdsArg.split(':'); ddsHost = ddsUrl[0]; ddsPort = ddsUrl[1]; } - final bool debugDds = argResults['debug-dds']; bool disableServiceAuthCodes = argResults['disable-service-auth-codes']; @@ -207,12 +198,7 @@ class RunCommand extends DartdevCommand { if (launchDds) { debugSession = _DebuggingSession(); if (!await debugSession.start( - ddsHost, - ddsPort, - disableServiceAuthCodes, - launchDevTools, - debugDds, - )) { + ddsHost, ddsPort, disableServiceAuthCodes)) { return errorExitCode; } } @@ -256,19 +242,10 @@ String maybeUriToFilename(String maybeUri) { class _DebuggingSession { Future start( - String host, - String port, - bool disableServiceAuthCodes, - bool enableDevTools, - bool debugDds, - ) async { - final sdkDir = dirname(sdk.dart); - final fullSdk = sdkDir.endsWith('bin'); - final ddsSnapshot = fullSdk + String host, String port, bool disableServiceAuthCodes) async { + final ddsSnapshot = (dirname(sdk.dart).endsWith('bin')) ? sdk.ddsSnapshot - : absolute(sdkDir, 'gen', 'dds.dart.snapshot'); - final devToolsBinaries = - fullSdk ? sdk.devToolsBinaries : absolute(sdkDir, 'devtools'); + : absolute(dirname(sdk.dart), 'gen', 'dds.dart.snapshot'); if (!Sdk.checkArtifactExists(ddsSnapshot)) { return false; } @@ -279,51 +256,30 @@ class _DebuggingSession { serviceInfo = await Service.getInfo(); } final process = await Process.start( - sdk.dart, - [ - if (debugDds) '--enable-vm-service=0', - ddsSnapshot, - serviceInfo.serverUri.toString(), - host, - port, - disableServiceAuthCodes.toString(), - enableDevTools.toString(), - devToolsBinaries, - debugDds.toString(), - ], - mode: ProcessStartMode.detachedWithStdio, - ); + sdk.dart, + [ + if (dirname(sdk.dart).endsWith('bin')) + sdk.ddsSnapshot + else + absolute(dirname(sdk.dart), 'gen', 'dds.dart.snapshot'), + serviceInfo.serverUri.toString(), + host, + port, + disableServiceAuthCodes.toString(), + ], + mode: ProcessStartMode.detachedWithStdio); final completer = Completer(); - const devToolsMessagePrefix = - 'The Dart DevTools debugger and profiler is available at:'; - if (debugDds) { - StreamSubscription stdoutSub; - stdoutSub = process.stdout.transform(utf8.decoder).listen((event) { - if (event.startsWith(devToolsMessagePrefix)) { - final ddsDebuggingUri = event.split(' ').last; - print( - 'A DevTools debugger for DDS is available at: $ddsDebuggingUri', - ); - stdoutSub.cancel(); - } - }); - } - StreamSubscription stderrSub; - stderrSub = process.stderr.transform(utf8.decoder).listen((event) { - final result = json.decode(event) as Map; - final state = result['state']; - if (state == 'started') { - if (result.containsKey('devToolsUri')) { - final devToolsUri = result['devToolsUri']; - print('$devToolsMessagePrefix $devToolsUri'); - } - stderrSub.cancel(); + StreamSubscription sub; + sub = process.stderr.transform(utf8.decoder).listen((event) { + if (event == 'DDS started') { + sub.cancel(); completer.complete(); - } else { - stderrSub.cancel(); - completer.completeError( + } else if (event.contains('Failed to start DDS')) { + sub.cancel(); + completer.completeError(event.replaceAll( + 'Failed to start DDS', 'Could not start Observatory HTTP server', - ); + )); } }); try { diff --git a/pkg/dartdev/lib/src/sdk.dart b/pkg/dartdev/lib/src/sdk.dart index 426f8106fbd..3e8a12a8b2b 100644 --- a/pkg/dartdev/lib/src/sdk.dart +++ b/pkg/dartdev/lib/src/sdk.dart @@ -68,13 +68,6 @@ class Sdk { 'dds.dart.snapshot', ); - String get devToolsBinaries => path.absolute( - sdkPath, - 'bin', - 'resources', - 'devtools', - ); - String get pubSnapshot => path.absolute( sdkPath, 'bin', diff --git a/pkg/dartdev/test/commands/run_test.dart b/pkg/dartdev/test/commands/run_test.dart index 58a4d56fe2d..b8cc5e8da8c 100644 --- a/pkg/dartdev/test/commands/run_test.dart +++ b/pkg/dartdev/test/commands/run_test.dart @@ -2,8 +2,6 @@ // for details. 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 'dart:convert'; import 'dart:io'; import 'package:path/path.dart' as path; @@ -302,61 +300,4 @@ void main(List args) => print("$b $args"); expect(result.stderr, isEmpty); expect(result.exitCode, 0); }); - - group('DevTools', () { - const devToolsMessagePrefix = - 'The Dart DevTools debugger and profiler is available at: http://127.0.0.1:'; - - test('spawn simple', () async { - p = project(mainSrc: "void main() { print('Hello World'); }"); - ProcessResult result = p.runSync([ - 'run', - '--enable-vm-service', - p.relativeFilePath, - ]); - expect(result.stdout, contains(devToolsMessagePrefix)); - }); - - test('implicit spawn', () async { - p = project(mainSrc: "void main() { print('Hello World'); }"); - ProcessResult result = p.runSync([ - '--enable-vm-service', - p.relativeFilePath, - ]); - expect(result.stdout, contains(devToolsMessagePrefix)); - }); - - test( - 'spawn via SIGQUIT', - () async { - p = project( - mainSrc: - 'void main() { print("ready"); int i = 0; while(true) { i++; } }', - ); - Process process = await p.start([ - p.relativeFilePath, - ]); - - final readyCompleter = Completer(); - final completer = Completer(); - - StreamSubscription sub; - sub = process.stdout.transform(utf8.decoder).listen((event) async { - if (event.contains('ready')) { - readyCompleter.complete(); - } else if (event.contains(devToolsMessagePrefix)) { - await sub.cancel(); - completer.complete(); - } - }); - // Wait for process to start. - await readyCompleter.future; - process.kill(ProcessSignal.sigquit); - await completer.future; - process.kill(); - }, - // No support for SIGQUIT on Windows. - skip: Platform.isWindows, - ); - }); } diff --git a/pkg/dds/CHANGELOG.md b/pkg/dds/CHANGELOG.md index b39156ed0c5..3db7549e55e 100644 --- a/pkg/dds/CHANGELOG.md +++ b/pkg/dds/CHANGELOG.md @@ -1,5 +1,4 @@ -# 1.8.0-dev -- Add support for launching DevTools from DDS. +# 1.7.7-dev - Fixed issue where two clients subscribing to the same stream in close succession could result in DDS sending multiple `streamListen` requests to the VM service. diff --git a/pkg/dds/bin/dds.dart b/pkg/dds/bin/dds.dart index 45673f515af..9937d26ad0b 100644 --- a/pkg/dds/bin/dds.dart +++ b/pkg/dds/bin/dds.dart @@ -4,7 +4,6 @@ // @dart=2.10 -import 'dart:convert'; import 'dart:io'; import 'package:dds/dds.dart'; @@ -17,9 +16,6 @@ import 'package:dds/dds.dart'; /// - DDS bind address /// - DDS port /// - Disable service authentication codes -/// - Start DevTools -/// - DevTools build directory -/// - Enable logging Future main(List args) async { if (args.isEmpty) return; @@ -41,37 +37,16 @@ Future main(List args) async { port: int.parse(args[2]), ); final disableServiceAuthCodes = args[3] == 'true'; - - final startDevTools = args[4] == 'true'; - Uri devToolsBuildDirectory; - if (args[5].isNotEmpty) { - devToolsBuildDirectory = Uri.file(args[5]); - } - final logRequests = args[6] == 'true'; try { // TODO(bkonyi): add retry logic similar to that in vmservice_server.dart // See https://github.com/dart-lang/sdk/issues/43192. - final dds = await DartDevelopmentService.startDartDevelopmentService( + await DartDevelopmentService.startDartDevelopmentService( remoteVmServiceUri, serviceUri: serviceUri, enableAuthCodes: !disableServiceAuthCodes, - devToolsConfiguration: startDevTools - ? DevToolsConfiguration( - enable: startDevTools, - customBuildDirectoryPath: devToolsBuildDirectory, - ) - : null, - logRequests: logRequests, ); - stderr.write(json.encode({ - 'state': 'started', - if (dds.devToolsUri != null) 'devToolsUri': dds.devToolsUri.toString(), - })); - } catch (e, st) { - stderr.write(json.encode({ - 'state': 'error', - 'error': '$e', - 'stacktrace': '$st', - })); + stderr.write('DDS started'); + } catch (e) { + stderr.writeln('Failed to start DDS:\n$e'); } } diff --git a/pkg/dds/lib/dds.dart b/pkg/dds/lib/dds.dart index f0e913bf62f..f7c7a05594e 100644 --- a/pkg/dds/lib/dds.dart +++ b/pkg/dds/lib/dds.dart @@ -44,8 +44,6 @@ abstract class DartDevelopmentService { Uri serviceUri, bool enableAuthCodes = true, bool ipv6 = false, - DevToolsConfiguration devToolsConfiguration = const DevToolsConfiguration(), - bool logRequests = false, }) async { if (remoteVmServiceUri == null) { throw ArgumentError.notNull('remoteVmServiceUri'); @@ -82,8 +80,6 @@ abstract class DartDevelopmentService { serviceUri, enableAuthCodes, ipv6, - devToolsConfiguration, - logRequests, ); await service.startService(); return service; @@ -129,11 +125,6 @@ abstract class DartDevelopmentService { /// Returns `null` if the service is not running. Uri get wsUri; - /// The HTTP [Uri] of the hosted DevTools instance. - /// - /// Returns `null` if DevTools is not running. - Uri get devToolsUri; - /// Set to `true` if this instance of [DartDevelopmentService] is accepting /// requests. bool get isRunning; @@ -177,13 +168,3 @@ class DartDevelopmentServiceException implements Exception { final int errorCode; final String message; } - -class DevToolsConfiguration { - const DevToolsConfiguration({ - this.enable = false, - this.customBuildDirectoryPath, - }); - - final bool enable; - final Uri customBuildDirectoryPath; -} diff --git a/pkg/dds/lib/src/client.dart b/pkg/dds/lib/src/client.dart index 9ceb1628f03..f81bd25b400 100644 --- a/pkg/dds/lib/src/client.dart +++ b/pkg/dds/lib/src/client.dart @@ -21,25 +21,27 @@ import 'stream_manager.dart'; /// Representation of a single DDS client which manages the connection and /// DDS request intercepting / forwarding. class DartDevelopmentServiceClient { - DartDevelopmentServiceClient.fromWebSocket( + factory DartDevelopmentServiceClient.fromWebSocket( DartDevelopmentService dds, WebSocketChannel ws, json_rpc.Peer vmServicePeer, - ) : this._( - dds, - ws, - vmServicePeer, - ); + ) => + DartDevelopmentServiceClient._( + dds, + ws, + vmServicePeer, + ); - DartDevelopmentServiceClient.fromSSEConnection( + factory DartDevelopmentServiceClient.fromSSEConnection( DartDevelopmentService dds, SseConnection sse, json_rpc.Peer vmServicePeer, - ) : this._( - dds, - sse, - vmServicePeer, - ); + ) => + DartDevelopmentServiceClient._( + dds, + sse, + vmServicePeer, + ); DartDevelopmentServiceClient._( this.dds, diff --git a/pkg/dds/lib/src/constants.dart b/pkg/dds/lib/src/constants.dart index b69ae7c9085..2466390d62a 100644 --- a/pkg/dds/lib/src/constants.dart +++ b/pkg/dds/lib/src/constants.dart @@ -16,10 +16,6 @@ abstract class RPCResponses { }; } -// Give connections time to reestablish before considering them closed. -// Required to reestablish connections killed by UberProxy. -const sseKeepAlive = Duration(seconds: 30); - abstract class PauseTypeMasks { static const pauseOnStartMask = 1 << 0; static const pauseOnReloadMask = 1 << 1; diff --git a/pkg/dds/lib/src/dds_impl.dart b/pkg/dds/lib/src/dds_impl.dart index 85be647102d..db355fbad4e 100644 --- a/pkg/dds/lib/src/dds_impl.dart +++ b/pkg/dds/lib/src/dds_impl.dart @@ -24,8 +24,6 @@ import '../dds.dart'; import 'binary_compatible_peer.dart'; import 'client.dart'; import 'client_manager.dart'; -import 'constants.dart'; -import 'devtools/devtools_handler.dart'; import 'expression_evaluator.dart'; import 'isolate_manager.dart'; import 'stream_manager.dart'; @@ -53,13 +51,7 @@ WebSocketChannel _defaultWebSocketBuilder(Uri uri) { class DartDevelopmentServiceImpl implements DartDevelopmentService { DartDevelopmentServiceImpl( - this._remoteVmServiceUri, - this._uri, - this._authCodesEnabled, - this._ipv6, - this._devToolsConfiguration, - this.shouldLogRequests, - ) { + this._remoteVmServiceUri, this._uri, this._authCodesEnabled, this._ipv6) { _clientManager = ClientManager(this); _expressionEvaluator = ExpressionEvaluator(this); _isolateManager = IsolateManager(this); @@ -121,26 +113,20 @@ class DartDevelopmentServiceImpl implements DartDevelopmentService { (_ipv6 ? InternetAddress.loopbackIPv6 : InternetAddress.loopbackIPv4) .host; final port = uri?.port ?? 0; - final pipeline = const Pipeline(); - if (shouldLogRequests) { - pipeline.addMiddleware( - logRequests( - logger: (String message, bool isError) { - print('Log: $message'); - }, - ), - ); - } - pipeline.addMiddleware(_authCodeMiddleware); - final handler = pipeline.addHandler(_handlers().handler); + // Start the DDS server. - _server = await io.serve(handler, host, port); + _server = await io.serve( + const Pipeline() + .addMiddleware(_authCodeMiddleware) + .addHandler(_handlers().handler), + host, + port); final tmpUri = Uri( scheme: 'http', host: host, port: _server.port, - path: '$authCode/', + path: '$_authCode/', ); // Notify the VM service that this client is DDS and that it should close @@ -171,7 +157,7 @@ class DartDevelopmentServiceImpl implements DartDevelopmentService { return; } _shuttingDown = true; - // Don't accept any more HTTP requests. + // Don't accept anymore HTTP requests. await _server?.close(); // Close connections to clients. @@ -211,7 +197,7 @@ class DartDevelopmentServiceImpl implements DartDevelopmentService { return forbidden; } final authToken = pathSegments[0]; - if (authToken != authCode) { + if (authToken != _authCode) { return forbidden; } // Creates a new request with the authentication code stripped from @@ -247,12 +233,18 @@ class DartDevelopmentServiceImpl implements DartDevelopmentService { }); Handler _sseHandler() { - final handler = SseHandler( - authCodesEnabled - ? Uri.parse('/$authCode/$_kSseHandlerPath') - : Uri.parse('/$_kSseHandlerPath'), - keepAlive: sseKeepAlive, - ); + // Give connections time to reestablish before considering them closed. + // Required to reestablish connections killed by UberProxy. + const keepAlive = Duration(seconds: 30); + final handler = authCodesEnabled + ? SseHandler( + Uri.parse('/$_authCode/$_kSseHandlerPath'), + keepAlive: keepAlive, + ) + : SseHandler( + Uri.parse('/$_kSseHandlerPath'), + keepAlive: keepAlive, + ); handler.connections.rest.listen((sseConnection) { final client = DartDevelopmentServiceClient.fromSSEConnection( @@ -267,18 +259,10 @@ class DartDevelopmentServiceImpl implements DartDevelopmentService { } Handler _httpHandler() { - if (_devToolsConfiguration != null && _devToolsConfiguration.enable) { - // Install the DevTools handlers and forward any unhandled HTTP requests to - // the VM service. - final buildDir = - _devToolsConfiguration.customBuildDirectoryPath?.toFilePath(); - return devtoolsHandler( - dds: this, - buildDir: buildDir, - notFoundHandler: proxyHandler(remoteVmServiceUri), - ); - } - return proxyHandler(remoteVmServiceUri); + // DDS doesn't support any HTTP requests itself, so we just forward all of + // them to the VM service. + final cascade = Cascade().add(proxyHandler(remoteVmServiceUri)); + return cascade.handler; } List _cleanupPathSegments(Uri uri) { @@ -312,43 +296,14 @@ class DartDevelopmentServiceImpl implements DartDevelopmentService { return uri.replace(scheme: 'sse', pathSegments: pathSegments); } - Uri _toDevTools(Uri uri) { - // The DevTools URI is a bit strange as the query parameters appear after - // the fragment. There's no nice way to encode the query parameters - // properly, so we create another Uri just to grab the formatted query. - // The result will need to have '/?' prepended when being used as the - // fragment to get the correct format. - final query = Uri( - queryParameters: { - 'uri': wsUri.toString(), - }, - ).query; - return Uri( - scheme: 'http', - host: uri.host, - port: uri.port, - pathSegments: [ - ...uri.pathSegments.where( - (e) => e.isNotEmpty, - ), - 'devtools', - '', - ], - fragment: '/?$query', - ); - } - String getNamespace(DartDevelopmentServiceClient client) => clientManager.clients.keyOf(client); @override bool get authCodesEnabled => _authCodesEnabled; final bool _authCodesEnabled; - String get authCode => _authCode; String _authCode; - final bool shouldLogRequests; - @override Uri get remoteVmServiceUri => _remoteVmServiceUri; @@ -358,21 +313,17 @@ class DartDevelopmentServiceImpl implements DartDevelopmentService { @override Uri get uri => _uri; - Uri _uri; @override Uri get sseUri => _toSse(_uri); Uri get wsUri => _toWebSocket(_uri); - - Uri get devToolsUri => _toDevTools(_uri); + Uri _uri; final bool _ipv6; bool get isRunning => _uri != null; - final DevToolsConfiguration _devToolsConfiguration; - Future get done => _done.future; Completer _done = Completer(); bool _shuttingDown = false; diff --git a/pkg/dds/lib/src/devtools/devtools_client.dart b/pkg/dds/lib/src/devtools/devtools_client.dart deleted file mode 100644 index 5f8670ec8e3..00000000000 --- a/pkg/dds/lib/src/devtools/devtools_client.dart +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -// @dart=2.9 - -import 'dart:async'; - -import 'package:json_rpc_2/src/server.dart' as json_rpc; -import 'package:sse/src/server/sse_handler.dart'; -import 'package:stream_channel/stream_channel.dart'; - -import 'server_api.dart'; - -class LoggingMiddlewareSink implements StreamSink { - LoggingMiddlewareSink(this.sink); - - @override - void add(S event) { - print('DevTools SSE response: $event'); - sink.add(event); - } - - @override - void addError(Object error, [StackTrace stackTrace]) { - print('DevTools SSE error response: $error'); - sink.addError(error); - } - - @override - Future addStream(Stream stream) { - return sink.addStream(stream); - } - - @override - Future close() => sink.close(); - - @override - Future get done => sink.done; - - final StreamSink sink; -} - -/// Represents a DevTools client connection to the DevTools server API. -class DevToolsClient { - DevToolsClient.fromSSEConnection( - SseConnection sse, - bool loggingEnabled, - ) { - Stream stream = sse.stream; - StreamSink sink = sse.sink; - - if (loggingEnabled) { - stream = stream.map((String e) { - print('DevTools SSE request: $e'); - return e; - }); - sink = LoggingMiddlewareSink(sink); - } - - _server = json_rpc.Server( - StreamChannel(stream, sink), - strictProtocolChecks: false, - ); - _registerJsonRpcMethods(); - _server.listen(); - } - - void _registerJsonRpcMethods() { - _server.registerMethod('connected', (parameters) { - // Nothing to do here. - }); - - _server.registerMethod('currentPage', (parameters) { - // Nothing to do here. - }); - - _server.registerMethod('disconnected', (parameters) { - // Nothing to do here. - }); - - _server.registerMethod('getPreferenceValue', (parameters) { - final key = parameters['key'].asString; - final value = ServerApi.devToolsPreferences.properties[key]; - return value; - }); - - _server.registerMethod('setPreferenceValue', (parameters) { - final key = parameters['key'].asString; - final value = parameters['value'].value; - ServerApi.devToolsPreferences.properties[key] = value; - }); - } - - json_rpc.Server _server; -} diff --git a/pkg/dds/lib/src/devtools/devtools_handler.dart b/pkg/dds/lib/src/devtools/devtools_handler.dart deleted file mode 100644 index a0a4bf12e85..00000000000 --- a/pkg/dds/lib/src/devtools/devtools_handler.dart +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -// @dart=2.9 - -import 'dart:async'; - -import 'package:dds/src/constants.dart'; -import 'package:meta/meta.dart'; -import 'package:shelf/shelf.dart'; -import 'package:shelf_static/shelf_static.dart'; -import 'package:sse/server/sse_handler.dart'; - -import '../dds_impl.dart'; -import 'devtools_client.dart'; -import 'server_api.dart'; - -/// Returns a [Handler] which handles serving DevTools and the DevTools server -/// API under $DDS_URI/devtools/. -/// -/// [buildDir] is the path to the pre-compiled DevTools instance to be served. -/// -/// [notFoundHandler] is a [Handler] to which requests that could not be handled -/// by the DevTools handler are forwarded (e.g., a proxy to the VM service). -FutureOr devtoolsHandler({ - @required DartDevelopmentServiceImpl dds, - @required String buildDir, - @required Handler notFoundHandler, -}) { - // Serves the web assets for DevTools. - final devtoolsAssetHandler = createStaticHandler( - buildDir, - defaultDocument: 'index.html', - ); - - // Support DevTools client-server interface via SSE. - // Note: the handler path needs to match the full *original* path, not the - // current request URL (we remove '/devtools' in the initial router but we - // need to include it here). - const devToolsSseHandlerPath = '/devtools/api/sse'; - final devToolsApiHandler = SseHandler( - dds.authCodesEnabled - ? Uri.parse('/${dds.authCode}$devToolsSseHandlerPath') - : Uri.parse(devToolsSseHandlerPath), - keepAlive: sseKeepAlive, - ); - - devToolsApiHandler.connections.rest.listen( - (sseConnection) => DevToolsClient.fromSSEConnection( - sseConnection, - dds.shouldLogRequests, - ), - ); - - final devtoolsHandler = (Request request) { - // If the request isn't of the form api/ assume it's a request for - // DevTools assets. - if (request.url.pathSegments.length < 2 || - request.url.pathSegments.first != 'api') { - return devtoolsAssetHandler(request); - } - final method = request.url.pathSegments[1]; - if (method == 'ping') { - // Note: we have an 'OK' body response, otherwise the response has an - // incorrect status code (204 instead of 200). - return Response.ok('OK'); - } - if (method == 'sse') { - return devToolsApiHandler.handler(request); - } - if (!ServerApi.canHandle(request)) { - return Response.notFound('$method is not a valid API'); - } - return ServerApi.handle(request); - }; - - return (request) { - final pathSegments = request.url.pathSegments; - if (pathSegments.isEmpty || pathSegments.first != 'devtools') { - return notFoundHandler(request); - } - // Forward all requests to /devtools/* to the DevTools handler. - request = request.change(path: 'devtools'); - return devtoolsHandler(request); - }; -} diff --git a/pkg/dds/lib/src/devtools/file_system.dart b/pkg/dds/lib/src/devtools/file_system.dart deleted file mode 100644 index 9a05de70971..00000000000 --- a/pkg/dds/lib/src/devtools/file_system.dart +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2021 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. - -// @dart=2.9 - -// TODO(bkonyi): remove once package:devtools_server_api is available -// See https://github.com/flutter/devtools/issues/2958. - -import 'dart:convert'; -import 'dart:io'; - -import 'package:path/path.dart' as path; - -import 'usage.dart'; - -class LocalFileSystem { - static String _userHomeDir() { - final String envKey = - Platform.operatingSystem == 'windows' ? 'APPDATA' : 'HOME'; - final String value = Platform.environment[envKey]; - return value == null ? '.' : value; - } - - /// Returns the path to the DevTools storage directory. - static String devToolsDir() { - return path.join(_userHomeDir(), '.flutter-devtools'); - } - - /// Moves the .devtools file to ~/.flutter-devtools/.devtools if the .devtools file - /// exists in the user's home directory. - static void maybeMoveLegacyDevToolsStore() { - final file = File(path.join(_userHomeDir(), DevToolsUsage.storeName)); - if (file.existsSync()) { - ensureDevToolsDirectory(); - file.copySync(path.join(devToolsDir(), DevToolsUsage.storeName)); - file.deleteSync(); - } - } - - /// Creates the ~/.flutter-devtools directory if it does not already exist. - static void ensureDevToolsDirectory() { - Directory('${LocalFileSystem.devToolsDir()}').createSync(); - } - - /// Returns a DevTools file from the given path. - /// - /// Only files within ~/.flutter-devtools/ can be accessed. - static File devToolsFileFromPath(String pathFromDevToolsDir) { - if (pathFromDevToolsDir.contains('..')) { - // The passed in path should not be able to walk up the directory tree - // outside of the ~/.flutter-devtools/ directory. - return null; - } - ensureDevToolsDirectory(); - final file = File(path.join(devToolsDir(), pathFromDevToolsDir)); - if (!file.existsSync()) { - return null; - } - return file; - } - - /// Returns a DevTools file from the given path as encoded json. - /// - /// Only files within ~/.flutter-devtools/ can be accessed. - static String devToolsFileAsJson(String pathFromDevToolsDir) { - final file = devToolsFileFromPath(pathFromDevToolsDir); - if (file == null) return null; - - final fileName = path.basename(file.path); - if (!fileName.endsWith('.json')) return null; - - final content = file.readAsStringSync(); - final json = jsonDecode(content); - json['lastModifiedTime'] = file.lastModifiedSync().toString(); - return jsonEncode(json); - } - - /// Whether the flutter store file exists. - static bool flutterStoreExists() { - final flutterStore = File('${_userHomeDir()}/.flutter'); - return flutterStore.existsSync(); - } -} diff --git a/pkg/dds/lib/src/devtools/server_api.dart b/pkg/dds/lib/src/devtools/server_api.dart deleted file mode 100644 index b866f4448d3..00000000000 --- a/pkg/dds/lib/src/devtools/server_api.dart +++ /dev/null @@ -1,230 +0,0 @@ -// Copyright 2021 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. - -// @dart=2.9 - -// TODO(bkonyi): remove once package:devtools_server_api is available -// See https://github.com/flutter/devtools/issues/2958. - -import 'dart:async'; -import 'dart:convert'; -import 'dart:io'; - -import 'package:devtools_shared/devtools_shared.dart'; -import 'package:shelf/shelf.dart' as shelf; - -import 'file_system.dart'; -import 'usage.dart'; - -/// The DevTools server API. -/// -/// This defines endpoints that serve all requests that come in over api/. -class ServerApi { - static const errorNoActiveSurvey = 'ERROR: setActiveSurvey not called.'; - - /// Determines whether or not [request] is an API call. - static bool canHandle(shelf.Request request) { - return request.url.path.startsWith(apiPrefix); - } - - /// Handles all requests. - /// - /// To override an API call, pass in a subclass of [ServerApi]. - static FutureOr handle( - shelf.Request request, [ - ServerApi api, - ]) { - api ??= ServerApi(); - switch (request.url.path) { - // ----- Flutter Tool GA store. ----- - case apiGetFlutterGAEnabled: - // Is Analytics collection enabled? - return api.getCompleted( - request, - json.encode(FlutterUsage.doesStoreExist ? _usage.enabled : null), - ); - case apiGetFlutterGAClientId: - // Flutter Tool GA clientId - ONLY get Flutter's clientId if enabled is - // true. - return (FlutterUsage.doesStoreExist) - ? api.getCompleted( - request, - json.encode(_usage.enabled ? _usage.clientId : null), - ) - : api.getCompleted( - request, - json.encode(null), - ); - - // ----- DevTools GA store. ----- - - case apiResetDevTools: - _devToolsUsage.reset(); - return api.getCompleted(request, json.encode(true)); - case apiGetDevToolsFirstRun: - // Has DevTools been run first time? To bring up welcome screen. - return api.getCompleted( - request, - json.encode(_devToolsUsage.isFirstRun), - ); - case apiGetDevToolsEnabled: - // Is DevTools Analytics collection enabled? - return api.getCompleted(request, json.encode(_devToolsUsage.enabled)); - case apiSetDevToolsEnabled: - // Enable or disable DevTools analytics collection. - final queryParams = request.requestedUri.queryParameters; - if (queryParams.containsKey(devToolsEnabledPropertyName)) { - _devToolsUsage.enabled = - json.decode(queryParams[devToolsEnabledPropertyName]); - } - return api.setCompleted(request, json.encode(_devToolsUsage.enabled)); - - // ----- DevTools survey store. ----- - - case apiSetActiveSurvey: - // Assume failure. - bool result = false; - - // Set the active survey used to store subsequent apiGetSurveyActionTaken, - // apiSetSurveyActionTaken, apiGetSurveyShownCount, and - // apiIncrementSurveyShownCount calls. - final queryParams = request.requestedUri.queryParameters; - if (queryParams.keys.length == 1 && - queryParams.containsKey(activeSurveyName)) { - final String theSurveyName = queryParams[activeSurveyName]; - - // Set the current activeSurvey. - _devToolsUsage.activeSurvey = theSurveyName; - result = true; - } - - return api.getCompleted(request, json.encode(result)); - case apiGetSurveyActionTaken: - // Request setActiveSurvey has not been requested. - if (_devToolsUsage.activeSurvey == null) { - return api.badRequest('$errorNoActiveSurvey ' - '- $apiGetSurveyActionTaken'); - } - // SurveyActionTaken has the survey been acted upon (taken or dismissed) - return api.getCompleted( - request, - json.encode(_devToolsUsage.surveyActionTaken), - ); - // TODO(terry): remove the query param logic for this request. - // setSurveyActionTaken should only be called with the value of true, so - // we can remove the extra complexity. - case apiSetSurveyActionTaken: - // Request setActiveSurvey has not been requested. - if (_devToolsUsage.activeSurvey == null) { - return api.badRequest('$errorNoActiveSurvey ' - '- $apiSetSurveyActionTaken'); - } - // Set the SurveyActionTaken. - // Has the survey been taken or dismissed.. - final queryParams = request.requestedUri.queryParameters; - if (queryParams.containsKey(surveyActionTakenPropertyName)) { - _devToolsUsage.surveyActionTaken = - json.decode(queryParams[surveyActionTakenPropertyName]); - } - return api.setCompleted( - request, - json.encode(_devToolsUsage.surveyActionTaken), - ); - case apiGetSurveyShownCount: - // Request setActiveSurvey has not been requested. - if (_devToolsUsage.activeSurvey == null) { - return api.badRequest('$errorNoActiveSurvey ' - '- $apiGetSurveyShownCount'); - } - // SurveyShownCount how many times have we asked to take survey. - return api.getCompleted( - request, - json.encode(_devToolsUsage.surveyShownCount), - ); - case apiIncrementSurveyShownCount: - // Request setActiveSurvey has not been requested. - if (_devToolsUsage.activeSurvey == null) { - return api.badRequest('$errorNoActiveSurvey ' - '- $apiIncrementSurveyShownCount'); - } - // Increment the SurveyShownCount, we've asked about the survey. - _devToolsUsage.incrementSurveyShownCount(); - return api.getCompleted( - request, - json.encode(_devToolsUsage.surveyShownCount), - ); - case apiGetBaseAppSizeFile: - final queryParams = request.requestedUri.queryParameters; - if (queryParams.containsKey(baseAppSizeFilePropertyName)) { - final filePath = queryParams[baseAppSizeFilePropertyName]; - final fileJson = LocalFileSystem.devToolsFileAsJson(filePath); - if (fileJson == null) { - return api.badRequest('No JSON file available at $filePath.'); - } - return api.getCompleted(request, fileJson); - } - return api.badRequest('Request for base app size file does not ' - 'contain a query parameter with the expected key: ' - '$baseAppSizeFilePropertyName'); - case apiGetTestAppSizeFile: - final queryParams = request.requestedUri.queryParameters; - if (queryParams.containsKey(testAppSizeFilePropertyName)) { - final filePath = queryParams[testAppSizeFilePropertyName]; - final fileJson = LocalFileSystem.devToolsFileAsJson(filePath); - if (fileJson == null) { - return api.badRequest('No JSON file available at $filePath.'); - } - return api.getCompleted(request, fileJson); - } - return api.badRequest('Request for test app size file does not ' - 'contain a query parameter with the expected key: ' - '$testAppSizeFilePropertyName'); - default: - return api.notImplemented(request); - } - } - - // Accessing Flutter usage file e.g., ~/.flutter. - // NOTE: Only access the file if it exists otherwise Flutter Tool hasn't yet - // been run. - static final FlutterUsage _usage = - FlutterUsage.doesStoreExist ? FlutterUsage() : null; - - // Accessing DevTools usage file e.g., ~/.devtools - static final DevToolsUsage _devToolsUsage = DevToolsUsage(); - - static DevToolsUsage get devToolsPreferences => _devToolsUsage; - - /// Logs a page view in the DevTools server. - /// - /// In the open-source version of DevTools, Google Analytics handles this - /// without any need to involve the server. - FutureOr logScreenView(shelf.Request request) => - notImplemented(request); - - /// Return the value of the property. - FutureOr getCompleted(shelf.Request request, String value) => - shelf.Response.ok('$value'); - - /// Return the value of the property after the property value has been set. - FutureOr setCompleted(shelf.Request request, String value) => - shelf.Response.ok('$value'); - - /// A [shelf.Response] for API calls that encountered a request problem e.g., - /// setActiveSurvey not called. - /// - /// This is a 400 Bad Request response. - FutureOr badRequest([String logError]) { - if (logError != null) print(logError); - return shelf.Response(HttpStatus.badRequest); - } - - /// A [shelf.Response] for API calls that have not been implemented in this - /// server. - /// - /// This is a no-op 204 No Content response because returning 404 Not Found - /// creates unnecessary noise in the console. - FutureOr notImplemented(shelf.Request request) => - shelf.Response(HttpStatus.noContent); -} diff --git a/pkg/dds/lib/src/devtools/usage.dart b/pkg/dds/lib/src/devtools/usage.dart deleted file mode 100644 index afa35d72805..00000000000 --- a/pkg/dds/lib/src/devtools/usage.dart +++ /dev/null @@ -1,236 +0,0 @@ -// Copyright 2021 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. - -// @dart=2.9 - -// TODO(bkonyi): remove once package:devtools_server_api is available -// See https://github.com/flutter/devtools/issues/2958. - -import 'dart:convert'; -import 'dart:io'; - -import 'package:path/path.dart' as path; -import 'package:usage/usage_io.dart'; - -import 'file_system.dart'; - -/// Access the file '~/.flutter'. -class FlutterUsage { - /// Create a new Usage instance; [versionOverride] and [configDirOverride] are - /// used for testing. - FlutterUsage({ - String settingsName = 'flutter', - String versionOverride, - String configDirOverride, - }) { - _analytics = AnalyticsIO('', settingsName, ''); - } - - Analytics _analytics; - - /// Does the .flutter store exist? - static bool get doesStoreExist { - return LocalFileSystem.flutterStoreExists(); - } - - bool get isFirstRun => _analytics.firstRun; - - bool get enabled => _analytics.enabled; - - set enabled(bool value) => _analytics.enabled = value; - - String get clientId => _analytics.clientId; -} - -// Access the DevTools on disk store (~/.devtools/.devtools). -class DevToolsUsage { - /// Create a new Usage instance; [versionOverride] and [configDirOverride] are - /// used for testing. - DevToolsUsage({ - String versionOverride, - String configDirOverride, - }) { - LocalFileSystem.maybeMoveLegacyDevToolsStore(); - properties = IOPersistentProperties( - storeName, - documentDirPath: LocalFileSystem.devToolsDir(), - ); - } - - static const storeName = '.devtools'; - - /// The activeSurvey is the property name of a top-level property - /// existing or created in the file ~/.devtools - /// If the property doesn't exist it is created with default survey values: - /// - /// properties[activeSurvey]['surveyActionTaken'] = false; - /// properties[activeSurvey]['surveyShownCount'] = 0; - /// - /// It is a requirement that the API apiSetActiveSurvey must be called before - /// calling any survey method on DevToolsUsage (addSurvey, rewriteActiveSurvey, - /// surveyShownCount, incrementSurveyShownCount, or surveyActionTaken). - String _activeSurvey; - - IOPersistentProperties properties; - - static const _surveyActionTaken = 'surveyActionTaken'; - static const _surveyShownCount = 'surveyShownCount'; - - void reset() { - properties.remove('firstRun'); - properties['enabled'] = false; - } - - bool get isFirstRun { - properties['firstRun'] = properties['firstRun'] == null; - return properties['firstRun']; - } - - bool get enabled { - if (properties['enabled'] == null) { - properties['enabled'] = false; - } - - return properties['enabled']; - } - - set enabled(bool value) { - properties['enabled'] = value; - return properties['enabled']; - } - - bool surveyNameExists(String surveyName) => properties[surveyName] != null; - - void _addSurvey(String surveyName) { - assert(activeSurvey != null); - assert(activeSurvey == surveyName); - rewriteActiveSurvey(false, 0); - } - - String get activeSurvey => _activeSurvey; - - set activeSurvey(String surveyName) { - assert(surveyName != null); - _activeSurvey = surveyName; - - if (!surveyNameExists(activeSurvey)) { - // Create the survey if property is non-existent in ~/.devtools - _addSurvey(activeSurvey); - } - } - - /// Need to rewrite the entire survey structure for property to be persisted. - void rewriteActiveSurvey(bool actionTaken, int shownCount) { - assert(activeSurvey != null); - properties[activeSurvey] = { - _surveyActionTaken: actionTaken, - _surveyShownCount: shownCount, - }; - } - - int get surveyShownCount { - assert(activeSurvey != null); - final prop = properties[activeSurvey]; - if (prop[_surveyShownCount] == null) { - rewriteActiveSurvey(prop[_surveyActionTaken], 0); - } - return properties[activeSurvey][_surveyShownCount]; - } - - void incrementSurveyShownCount() { - assert(activeSurvey != null); - surveyShownCount; // Ensure surveyShownCount has been initialized. - final prop = properties[activeSurvey]; - rewriteActiveSurvey(prop[_surveyActionTaken], prop[_surveyShownCount] + 1); - } - - bool get surveyActionTaken { - assert(activeSurvey != null); - return properties[activeSurvey][_surveyActionTaken] == true; - } - - set surveyActionTaken(bool value) { - assert(activeSurvey != null); - final prop = properties[activeSurvey]; - rewriteActiveSurvey(value, prop[_surveyShownCount]); - } -} - -abstract class PersistentProperties { - PersistentProperties(this.name); - - final String name; - - dynamic operator [](String key); - - void operator []=(String key, dynamic value); - - /// Re-read settings from the backing store. - /// - /// May be a no-op on some platforms. - void syncSettings(); -} - -const JsonEncoder _jsonEncoder = JsonEncoder.withIndent(' '); - -class IOPersistentProperties extends PersistentProperties { - IOPersistentProperties( - String name, { - String documentDirPath, - }) : super(name) { - final String fileName = name.replaceAll(' ', '_'); - documentDirPath ??= LocalFileSystem.devToolsDir(); - _file = File(path.join(documentDirPath, fileName)); - if (!_file.existsSync()) { - _file.createSync(recursive: true); - } - syncSettings(); - } - - IOPersistentProperties.fromFile(File file) : super(path.basename(file.path)) { - _file = file; - if (!_file.existsSync()) { - _file.createSync(recursive: true); - } - syncSettings(); - } - - File _file; - - Map _map; - - @override - dynamic operator [](String key) => _map[key]; - - @override - void operator []=(String key, dynamic value) { - if (value == null && !_map.containsKey(key)) return; - if (_map[key] == value) return; - - if (value == null) { - _map.remove(key); - } else { - _map[key] = value; - } - - try { - _file.writeAsStringSync(_jsonEncoder.convert(_map) + '\n'); - } catch (_) {} - } - - @override - void syncSettings() { - try { - String contents = _file.readAsStringSync(); - if (contents.isEmpty) contents = '{}'; - _map = jsonDecode(contents); - } catch (_) { - _map = {}; - } - } - - void remove(String propertyName) { - _map.remove(propertyName); - } -} diff --git a/pkg/dds/pubspec.yaml b/pkg/dds/pubspec.yaml index a69236cd945..221e3df8821 100644 --- a/pkg/dds/pubspec.yaml +++ b/pkg/dds/pubspec.yaml @@ -3,7 +3,7 @@ description: >- A library used to spawn the Dart Developer Service, used to communicate with a Dart VM Service instance. -version: 1.8.0-dev +version: 1.7.6 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/dds @@ -12,21 +12,18 @@ environment: dependencies: async: ^2.4.1 - devtools_shared: ^2.0.0 json_rpc_2: ^2.2.0 meta: ^1.1.8 - path: ^1.8.0 pedantic: ^1.7.0 shelf: ^1.0.0 shelf_proxy: ^1.0.0 - shelf_static: ^1.0.0-dev shelf_web_socket: ^1.0.0 sse: ^3.7.0 stream_channel: ^2.0.0 - usage: ^4.0.0 vm_service: ^6.0.1-nullsafety.0 web_socket_channel: ^2.0.0 dev_dependencies: + shelf_static: ^1.0.0 test: ^1.0.0 webdriver: ^3.0.0 diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc index 95c7166d300..ee3510997a2 100644 --- a/runtime/bin/main.cc +++ b/runtime/bin/main.cc @@ -553,12 +553,13 @@ static Dart_Isolate CreateAndSetupServiceIsolate(const char* script_uri, vm_service_server_port = 0; } - // We do not want to wait for DDS to advertise availability of VM service in - // the following scenarios: - // - The DartDev CLI is disabled (CLI isolate starts DDS) and VM service is - // enabled. - // TODO(bkonyi): do we want to tie DevTools / DDS to the CLI in the long run? - bool wait_for_dds_to_advertise_service = !Options::disable_dart_dev(); + // We do not want to wait for DDS to advertise availability of VM service in the + // following scenarios: + // - When the VM service is disabled (can be started at a later time via SIGQUIT). + // - The DartDev CLI is disabled (CLI isolate starts DDS) and VM service is enabled. + bool wait_for_dds_to_advertise_service = + !Options::disable_dart_dev() && Options::enable_vm_service(); + // Load embedder specific bits and return. if (!VmService::Setup( Options::disable_dart_dev() ? Options::vm_service_server_ip() diff --git a/runtime/bin/main_options.cc b/runtime/bin/main_options.cc index 77b794c8e03..e60f6c82ae7 100644 --- a/runtime/bin/main_options.cc +++ b/runtime/bin/main_options.cc @@ -583,7 +583,7 @@ bool Options::ParseArguments(int argc, run_command = true; } if (!Options::disable_dart_dev() && enable_vm_service_ && run_command) { - const char* dds_format_str = "--launch-dds=%s\\:%d"; + const char* dds_format_str = "--launch-dds=%s:%d"; size_t size = snprintf(nullptr, 0, dds_format_str, vm_service_server_ip(), vm_service_server_port()); @@ -603,7 +603,6 @@ bool Options::ParseArguments(int argc, first_option = false; } } - // Verify consistency of arguments. // snapshot_depfile is an alias for depfile. Passing them both is an error. diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn index 13900927b88..15a1abfd32c 100644 --- a/sdk/BUILD.gn +++ b/sdk/BUILD.gn @@ -252,18 +252,6 @@ copy_tree_specs += [ }, ] -# This rule copies the pre-built DevTools application to -# bin/resources/devtools/ -copy_tree_specs += [ - { - target = "copy_prebuilt_devtools" - visibility = [ ":create_common_sdk" ] - source = "../third_party/devtools/web" - dest = "$root_out_dir/dart-sdk/bin/resources/devtools" - ignore_patterns = "{}" - }, -] - # This loop generates rules to copy libraries to lib/ foreach(library, _full_sdk_libraries) { copy_tree_specs += [ @@ -823,7 +811,6 @@ group("create_common_sdk") { ":copy_libraries_dart", ":copy_libraries_specification", ":copy_license", - ":copy_prebuilt_devtools", ":copy_readme", ":copy_vm_dill_files", ":write_dartdoc_options", diff --git a/sdk/lib/_internal/vm/bin/vmservice_io.dart b/sdk/lib/_internal/vm/bin/vmservice_io.dart index 833e5a223e3..d1f8a5d3423 100644 --- a/sdk/lib/_internal/vm/bin/vmservice_io.dart +++ b/sdk/lib/_internal/vm/bin/vmservice_io.dart @@ -43,7 +43,6 @@ bool _waitForDdsToAdvertiseService = false; // HTTP server. Server? server; Future? serverFuture; -_DebuggingSession? ddsInstance; Server _lazyServerBoot() { var localServer = server; @@ -59,90 +58,6 @@ Server _lazyServerBoot() { return localServer; } -/// Responsible for launching a DevTools instance when the service is started -/// via SIGQUIT. -class _DebuggingSession { - Future start( - String host, - String port, - bool disableServiceAuthCodes, - bool enableDevTools, - ) async { - final dartPath = Uri.parse(Platform.resolvedExecutable); - final dartDir = [ - '', // Include leading '/' - ...dartPath.pathSegments.sublist( - 0, - dartPath.pathSegments.length - 1, - ), - ].join('/'); - - final fullSdk = dartDir.endsWith('bin'); - - final ddsSnapshot = [ - dartDir, - fullSdk ? 'snapshots' : 'gen', - 'dds.dart.snapshot', - ].join('/'); - - final devToolsBinaries = [ - dartDir, - if (fullSdk) 'resources', - 'devtools', - ].join('/'); - - const enableLogging = false; - _process = await Process.start( - dartPath.toString(), - [ - ddsSnapshot, - server!.serverAddress!.toString(), - host, - port, - disableServiceAuthCodes.toString(), - enableDevTools.toString(), - devToolsBinaries, - enableLogging.toString(), - ], - mode: ProcessStartMode.detachedWithStdio, - ); - final completer = Completer(); - late StreamSubscription stderrSub; - stderrSub = _process!.stderr.transform(utf8.decoder).listen((event) { - final result = json.decode(event) as Map; - final state = result['state']; - if (state == 'started') { - if (result.containsKey('devToolsUri')) { - // NOTE: update pkg/dartdev/lib/src/commands/run.dart if this message - // is changed to ensure consistency. - const devToolsMessagePrefix = - 'The Dart DevTools debugger and profiler is available at:'; - final devToolsUri = result['devToolsUri']; - print('$devToolsMessagePrefix $devToolsUri'); - } - stderrSub.cancel(); - completer.complete(); - } else { - stderrSub.cancel(); - completer.completeError( - 'Could not start Observatory HTTP server', - ); - } - }); - try { - await completer.future; - return true; - } catch (e) { - stderr.write(e); - return false; - } - } - - void shutdown() => _process!.kill(); - - Process? _process; -} - Future cleanupCallback() async { // Cancel the sigquit subscription. if (_signalSubscription != null) { @@ -306,6 +221,10 @@ void webServerAcceptNewWebSocketConnections(bool enable) { _server.acceptNewWebSocketConnections = enable; } +void _clearFuture(_) { + serverFuture = null; +} + _onSignal(ProcessSignal signal) { if (serverFuture != null) { // Still waiting. @@ -314,21 +233,9 @@ _onSignal(ProcessSignal signal) { final _server = _lazyServerBoot(); // Toggle HTTP server. if (_server.running) { - _server.shutdown(true).then((_) async { - ddsInstance?.shutdown(); - await VMService().clearState(); - serverFuture = null; - }); + _server.shutdown(true).then(_clearFuture); } else { - _server.startup().then((_) { - ddsInstance = _DebuggingSession() - ..start( - _server._ip, - _server._port.toString(), - false, - true, - ); - }); + _server.startup().then(_clearFuture); } } diff --git a/sdk/lib/_internal/vm/bin/vmservice_server.dart b/sdk/lib/_internal/vm/bin/vmservice_server.dart index f5742edd2e6..69aa7f8a9d1 100644 --- a/sdk/lib/_internal/vm/bin/vmservice_server.dart +++ b/sdk/lib/_internal/vm/bin/vmservice_server.dart @@ -26,9 +26,9 @@ class WebSocketClient extends Client { socket.done.then((_) => close()); } - Future disconnect() async { + disconnect() { if (socket != null) { - await socket.close(); + socket.close(); } } @@ -102,8 +102,8 @@ class HttpRequestClient extends Client { HttpRequestClient(this.request, VMService service) : super(service, sendEvents: false); - Future disconnect() async { - await request.response.close(); + disconnect() { + request.response.close(); close(); } diff --git a/sdk/lib/vmservice/vmservice.dart b/sdk/lib/vmservice/vmservice.dart index d492dcfa5c3..a3f7e8b0e4d 100644 --- a/sdk/lib/vmservice/vmservice.dart +++ b/sdk/lib/vmservice/vmservice.dart @@ -411,16 +411,6 @@ class VMService extends MessageRouter { replyPort.send(bytes); } - Future clearState() async { - // Create a copy of the set as a list because client.disconnect() will - // alter the connected clients set. - final clientsList = clients.toList(); - for (final client in clientsList) { - await client.disconnect(); - } - devfs.cleanup(); - } - Future _exit() async { isExiting = true; @@ -433,7 +423,14 @@ class VMService extends MessageRouter { // Close receive ports. isolateControlPort.close(); scriptLoadPort.close(); - await clearState(); + + // Create a copy of the set as a list because client.disconnect() will + // alter the connected clients set. + final clientsList = clients.toList(); + for (final client in clientsList) { + client.disconnect(); + } + devfs.cleanup(); final cleanup = VMServiceEmbedderHooks.cleanup; if (cleanup != null) { await cleanup(); diff --git a/third_party/devtools/update.sh b/third_party/devtools/update.sh index 077d758c333..a69f6ee421a 100755 --- a/third_party/devtools/update.sh +++ b/third_party/devtools/update.sh @@ -30,11 +30,12 @@ git checkout -b cipd_release $1 # to serve from DDS. mkdir cipd_package cp -R packages/devtools/build/ cipd_package/web +cp -r packages/devtools_server cipd_package cp -r packages/devtools_shared cipd_package cipd create \ -name dart/third_party/flutter/devtools \ -in cipd_package \ -install-mode copy \ - -tag git_revision:$1 + -tag revision:$1 diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json index 39d72729f45..bf63fe3858f 100644 --- a/tools/bots/test_matrix.json +++ b/tools/bots/test_matrix.json @@ -322,7 +322,6 @@ "xcodebuild/ReleaseSIMARM64C/", "xcodebuild/ReleaseX64/", "xcodebuild/ReleaseX64C/", - "pkg/", "samples/", "samples_2/", "samples-dev/", @@ -330,7 +329,6 @@ "third_party/android_tools/sdk/platform-tools/adb", "third_party/android_tools/ndk/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-strip", "third_party/android_tools/ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-strip", - "third_party/devtools/", "third_party/webdriver/", "third_party/pkg/", "third_party/pkg_tested/", diff --git a/tools/generate_package_config.dart b/tools/generate_package_config.dart index f8791cd7f3a..8d4ed5bbbd0 100644 --- a/tools/generate_package_config.dart +++ b/tools/generate_package_config.dart @@ -57,8 +57,6 @@ void main(List args) { packageDirectory( 'runtime/observatory_2/tests/service_2/observatory_test_package_2'), packageDirectory('sdk/lib/_internal/sdk_library_metadata'), - packageDirectory('third_party/devtools/devtools_server'), - packageDirectory('third_party/devtools/devtools_shared'), packageDirectory('third_party/pkg/protobuf/protobuf'), packageDirectory('tools/package_deps'), ]; diff --git a/utils/dartdev/BUILD.gn b/utils/dartdev/BUILD.gn index 3ce3bc38a15..7f33d990301 100644 --- a/utils/dartdev/BUILD.gn +++ b/utils/dartdev/BUILD.gn @@ -2,14 +2,12 @@ # for details. All rights reserved. Use of this source code is governed by a # BSD-style license that can be found in the LICENSE file. -import("../../build/dart/copy_tree.gni") import("../application_snapshot.gni") group("dartdev") { public_deps = [ ":copy_dartdev_kernel", ":copy_dartdev_snapshot", - ":copy_prebuilt_devtools", ] } @@ -41,15 +39,3 @@ application_snapshot("generate_dartdev_snapshot") { deps = [ "../dds:dds" ] output = "$root_gen_dir/dartdev.dart.snapshot" } - -copy_trees("copy_prebuilt_devtools") { - sources = [ - { - target = "copy_prebuilt_devtools" - visibility = [ ":dartdev" ] - source = "../../third_party/devtools/web" - dest = "$root_out_dir/devtools" - ignore_patterns = "{}" - }, - ] -}