diff --git a/dwds/lib/dart_web_debug_service.dart b/dwds/lib/dart_web_debug_service.dart new file mode 100644 index 000000000..1429aa676 --- /dev/null +++ b/dwds/lib/dart_web_debug_service.dart @@ -0,0 +1,173 @@ +// Copyright (c) 2022, 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:logging/logging.dart'; +import 'package:meta/meta.dart'; +import 'package:shelf/shelf.dart'; +import 'package:sse/server/sse_handler.dart'; +import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'; + +import 'data/build_result.dart'; +import 'src/connections/app_connection.dart'; +import 'src/connections/debug_connection.dart'; +import 'src/events.dart'; +import 'src/handlers/dev_handler.dart'; +import 'src/handlers/injector.dart'; +import 'src/handlers/socket_connections.dart'; +import 'src/loaders/strategy.dart'; +import 'src/readers/asset_reader.dart'; +import 'src/servers/devtools.dart'; +import 'src/servers/extension_backend.dart'; +import 'src/services/expression_compiler.dart'; +import 'src/utilities/sdk_configuration.dart'; + +typedef ConnectionProvider = Future Function(); + +/// The Dart Web Debug Service. +class Dwds { + static final _logger = Logger('DWDS'); + final Middleware middleware; + final Handler handler; + final DevTools _devTools; + final DevHandler _devHandler; + final AssetReader _assetReader; + final bool _enableDebugging; + + Dwds._( + this.middleware, + this._devTools, + this._devHandler, + this._assetReader, + this._enableDebugging, + ) : handler = _devHandler.handler; + + Stream get connectedApps => _devHandler.connectedApps; + + Stream get events => eventStream; + + StreamController get extensionDebugConnections => + _devHandler.extensionDebugConnections; + + Future stop() async { + await _devTools?.close(); + await _devHandler.close(); + await _assetReader.close(); + } + + Future debugConnection(AppConnection appConnection) async { + if (!_enableDebugging) throw StateError('Debugging is not enabled.'); + final appDebugServices = await _devHandler.loadAppServices(appConnection); + await appDebugServices.chromeProxyService.isInitialized; + return DebugConnection(appDebugServices); + } + + static Future start({ + @required AssetReader assetReader, + @required Stream buildResults, + @required ConnectionProvider chromeConnection, + @required LoadStrategy loadStrategy, + @required bool enableDebugging, + // TODO(annagrin): make expressionCompiler argument required + // [issue 881](https://github.com/dart-lang/webdev/issues/881) + ExpressionCompiler expressionCompiler, + bool enableDebugExtension, + String hostname, + bool useSseForDebugProxy, + bool useSseForDebugBackend, + bool useSseForInjectedClient, + UrlEncoder urlEncoder, + bool spawnDds, + // TODO(elliette): DevTools is inconsistently capitalized throughout this + // file. Change all occurances of devtools/Devtools to devTools/DevTools. + bool enableDevtoolsLaunch, + DevtoolsLauncher devtoolsLauncher, + bool launchDevToolsInNewWindow, + SdkConfigurationProvider sdkConfigurationProvider, + bool emitDebugEvents, + }) async { + hostname ??= 'localhost'; + enableDebugging ??= true; + enableDebugExtension ??= false; + useSseForDebugProxy ??= true; + useSseForDebugBackend ??= true; + useSseForInjectedClient ??= true; + enableDevtoolsLaunch ??= true; + launchDevToolsInNewWindow ??= true; + spawnDds ??= true; + globalLoadStrategy = loadStrategy; + emitDebugEvents ??= true; + + sdkConfigurationProvider ??= DefaultSdkConfigurationProvider(); + + DevTools devTools; + Future extensionUri; + ExtensionBackend extensionBackend; + if (enableDebugExtension) { + final handler = useSseForDebugBackend + ? SseSocketHandler(SseHandler(Uri.parse('/\$debug'), + // Proxy servers may actively kill long standing connections. + // Allow for clients to reconnect in a short window. Making the + // window too long may cause issues if the user closes a debug + // session and initites a new one during the keepAlive window. + keepAlive: const Duration(seconds: 5))) + : WebSocketSocketHandler(); + + extensionBackend = await ExtensionBackend.start(handler, hostname); + extensionUri = Future.value(Uri( + scheme: useSseForDebugBackend ? 'http' : 'ws', + host: extensionBackend.hostname, + port: extensionBackend.port, + path: r'$debug') + .toString()); + if (urlEncoder != null) extensionUri = urlEncoder(await extensionUri); + } + + final serveDevTools = devtoolsLauncher != null; + if (serveDevTools) { + devTools = await devtoolsLauncher(hostname); + final uri = + Uri(scheme: 'http', host: devTools.hostname, port: devTools.port); + _logger.info('Serving DevTools at $uri\n'); + } + + final injected = DwdsInjector( + loadStrategy, + useSseForInjectedClient: useSseForInjectedClient, + extensionUri: extensionUri, + enableDevtoolsLaunch: enableDevtoolsLaunch, + emitDebugEvents: emitDebugEvents, + ); + + final devHandler = DevHandler( + chromeConnection, + buildResults, + devTools, + assetReader, + loadStrategy, + hostname, + extensionBackend, + urlEncoder, + useSseForDebugProxy, + useSseForInjectedClient, + serveDevTools, + expressionCompiler, + injected, + spawnDds, + launchDevToolsInNewWindow, + sdkConfigurationProvider, + ); + + return Dwds._( + injected.middleware, + devTools, + devHandler, + assetReader, + enableDebugging, + ); + } +} diff --git a/dwds/lib/dwds.dart b/dwds/lib/dwds.dart index 613c3123a..fbf6198e9 100644 --- a/dwds/lib/dwds.dart +++ b/dwds/lib/dwds.dart @@ -4,28 +4,7 @@ // @dart = 2.9 -import 'dart:async'; - -import 'package:logging/logging.dart'; -import 'package:meta/meta.dart'; -import 'package:shelf/shelf.dart'; -import 'package:sse/server/sse_handler.dart'; -import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'; - -import 'data/build_result.dart'; -import 'src/connections/app_connection.dart'; -import 'src/connections/debug_connection.dart'; -import 'src/events.dart'; -import 'src/handlers/dev_handler.dart'; -import 'src/handlers/injector.dart'; -import 'src/handlers/socket_connections.dart'; -import 'src/loaders/strategy.dart'; -import 'src/readers/asset_reader.dart'; -import 'src/servers/devtools.dart'; -import 'src/servers/extension_backend.dart'; -import 'src/services/expression_compiler.dart'; -import 'src/utilities/sdk_configuration.dart'; - +export 'dart_web_debug_service.dart' show Dwds, ConnectionProvider; export 'src/connections/app_connection.dart' show AppConnection; export 'src/connections/debug_connection.dart' show DebugConnection; export 'src/debugging/metadata/provider.dart' @@ -52,149 +31,3 @@ export 'src/services/expression_compiler_service.dart' show ExpressionCompilerService; export 'src/utilities/sdk_configuration.dart' show SdkConfiguration, SdkConfigurationProvider; - -typedef ConnectionProvider = Future Function(); - -/// The Dart Web Debug Service. -class Dwds { - static final _logger = Logger('DWDS'); - final Middleware middleware; - final Handler handler; - final DevTools _devTools; - final DevHandler _devHandler; - final AssetReader _assetReader; - final bool _enableDebugging; - - Dwds._( - this.middleware, - this._devTools, - this._devHandler, - this._assetReader, - this._enableDebugging, - ) : handler = _devHandler.handler; - - Stream get connectedApps => _devHandler.connectedApps; - - Stream get events => eventStream; - - StreamController get extensionDebugConnections => - _devHandler.extensionDebugConnections; - - Future stop() async { - await _devTools?.close(); - await _devHandler.close(); - await _assetReader.close(); - } - - Future debugConnection(AppConnection appConnection) async { - if (!_enableDebugging) throw StateError('Debugging is not enabled.'); - final appDebugServices = await _devHandler.loadAppServices(appConnection); - await appDebugServices.chromeProxyService.isInitialized; - return DebugConnection(appDebugServices); - } - - static Future start({ - @required AssetReader assetReader, - @required Stream buildResults, - @required ConnectionProvider chromeConnection, - @required LoadStrategy loadStrategy, - @required bool enableDebugging, - // TODO(annagrin): make expressionCompiler argument required - // [issue 881](https://github.com/dart-lang/webdev/issues/881) - ExpressionCompiler expressionCompiler, - bool enableDebugExtension, - String hostname, - bool useSseForDebugProxy, - bool useSseForDebugBackend, - bool useSseForInjectedClient, - UrlEncoder urlEncoder, - bool spawnDds, - // TODO(elliette): DevTools is inconsistently capitalized throughout this - // file. Change all occurances of devtools/Devtools to devTools/DevTools. - bool enableDevtoolsLaunch, - DevtoolsLauncher devtoolsLauncher, - bool launchDevToolsInNewWindow, - SdkConfigurationProvider sdkConfigurationProvider, - bool emitDebugEvents, - }) async { - hostname ??= 'localhost'; - enableDebugging ??= true; - enableDebugExtension ??= false; - useSseForDebugProxy ??= true; - useSseForDebugBackend ??= true; - useSseForInjectedClient ??= true; - enableDevtoolsLaunch ??= true; - launchDevToolsInNewWindow ??= true; - spawnDds ??= true; - globalLoadStrategy = loadStrategy; - emitDebugEvents ??= true; - - sdkConfigurationProvider ??= DefaultSdkConfigurationProvider(); - - DevTools devTools; - Future extensionUri; - ExtensionBackend extensionBackend; - if (enableDebugExtension) { - final handler = useSseForDebugBackend - ? SseSocketHandler(SseHandler(Uri.parse('/\$debug'), - // Proxy servers may actively kill long standing connections. - // Allow for clients to reconnect in a short window. Making the - // window too long may cause issues if the user closes a debug - // session and initites a new one during the keepAlive window. - keepAlive: const Duration(seconds: 5))) - : WebSocketSocketHandler(); - - extensionBackend = await ExtensionBackend.start(handler, hostname); - extensionUri = Future.value(Uri( - scheme: useSseForDebugBackend ? 'http' : 'ws', - host: extensionBackend.hostname, - port: extensionBackend.port, - path: r'$debug') - .toString()); - if (urlEncoder != null) extensionUri = urlEncoder(await extensionUri); - } - - final serveDevTools = devtoolsLauncher != null; - if (serveDevTools) { - devTools = await devtoolsLauncher(hostname); - final uri = - Uri(scheme: 'http', host: devTools.hostname, port: devTools.port); - _logger.info('Serving DevTools at $uri\n'); - } - - final injected = DwdsInjector( - loadStrategy, - useSseForInjectedClient: useSseForInjectedClient, - extensionUri: extensionUri, - enableDevtoolsLaunch: enableDevtoolsLaunch, - emitDebugEvents: emitDebugEvents, - ); - - final devHandler = DevHandler( - chromeConnection, - buildResults, - devTools, - assetReader, - loadStrategy, - hostname, - extensionBackend, - urlEncoder, - useSseForDebugProxy, - useSseForInjectedClient, - serveDevTools, - expressionCompiler, - injected, - spawnDds, - launchDevToolsInNewWindow, - sdkConfigurationProvider, - ); - - return Dwds._( - injected.middleware, - devTools, - devHandler, - assetReader, - enableDebugging, - ); - } -} diff --git a/dwds/test/fixtures/server.dart b/dwds/test/fixtures/server.dart index dda4083ca..bf6bff7d3 100644 --- a/dwds/test/fixtures/server.dart +++ b/dwds/test/fixtures/server.dart @@ -8,8 +8,13 @@ import 'dart:io'; import 'package:build_daemon/data/build_status.dart' as daemon; import 'package:dds/devtools_server.dart'; +import 'package:dwds/asset_reader.dart'; +import 'package:dwds/dart_web_debug_service.dart'; import 'package:dwds/data/build_result.dart'; -import 'package:dwds/dwds.dart'; +import 'package:dwds/expression_compiler.dart'; +import 'package:dwds/src/loaders/require.dart'; +import 'package:dwds/src/servers/devtools.dart'; +import 'package:dwds/src/services/expression_compiler_service.dart'; import 'package:dwds/src/utilities/shared.dart'; import 'package:logging/logging.dart'; import 'package:shelf/shelf.dart';