diff --git a/webdev/lib/src/serve/dev_workflow.dart b/webdev/lib/src/serve/dev_workflow.dart index 8560f3b9d..53081bb7d 100644 --- a/webdev/lib/src/serve/dev_workflow.dart +++ b/webdev/lib/src/serve/dev_workflow.dart @@ -10,6 +10,7 @@ import 'package:build_daemon/data/build_status.dart'; import 'package:build_daemon/data/build_target.dart'; import 'package:build_daemon/data/server_log.dart'; import 'package:logging/logging.dart' as logging; +import 'package:shelf/shelf.dart'; import '../command/configuration.dart'; import '../daemon_client.dart'; @@ -64,12 +65,12 @@ Future _startChrome( } Future _startServerManager( - Configuration configuration, - Map targetPorts, - String workingDirectory, - BuildDaemonClient client, - DevTools devTools, -) async { + Configuration configuration, + Map targetPorts, + String workingDirectory, + BuildDaemonClient client, + DevTools devTools, + {Handler optionalHandler}) async { var assetPort = daemonPort(workingDirectory); var serverOptions = Set(); for (var target in targetPorts.keys) { @@ -78,6 +79,7 @@ Future _startServerManager( targetPorts[target], target, assetPort, + optionalHandler: optionalHandler, )); } logWriter(logging.Level.INFO, 'Starting resource servers...'); @@ -171,11 +173,9 @@ class DevWorkflow { Future get done => _doneCompleter.future; - static Future start( - Configuration configuration, - List buildOptions, - Map targetPorts, - ) async { + static Future start(Configuration configuration, + List buildOptions, Map targetPorts, + {Handler optionalHandler}) async { var workingDirectory = Directory.current.path; var client = await _startBuildDaemon(workingDirectory, buildOptions); logWriter(logging.Level.INFO, 'Registering build targets...'); @@ -184,7 +184,8 @@ class DevWorkflow { client.startBuild(); var devTools = await _startDevTools(configuration); var serverManager = await _startServerManager( - configuration, targetPorts, workingDirectory, client, devTools); + configuration, targetPorts, workingDirectory, client, devTools, + optionalHandler: optionalHandler); var chrome = await _startChrome(configuration, serverManager, client); return DevWorkflow._(client, chrome, devTools, serverManager); } diff --git a/webdev/lib/src/serve/webdev_server.dart b/webdev/lib/src/serve/webdev_server.dart index 0292a1276..ccfd3d743 100644 --- a/webdev/lib/src/serve/webdev_server.dart +++ b/webdev/lib/src/serve/webdev_server.dart @@ -22,13 +22,10 @@ class ServerOptions { final int port; final String target; final int daemonPort; + final Handler optionalHandler; - ServerOptions( - this.configuration, - this.port, - this.target, - this.daemonPort, - ); + ServerOptions(this.configuration, this.port, this.target, this.daemonPort, + {this.optionalHandler}); } class WebDevServer { @@ -80,6 +77,10 @@ class WebDevServer { ); cascade = cascade.add(devHandler.handler).add(assetHandler.handler); + if (options.optionalHandler != null) { + cascade = cascade.add(options.optionalHandler); + } + var hostname = options.configuration.hostname; var server = await HttpMultiServer.bind(hostname, options.port); shelf_io.serveRequests(server, pipeline.addHandler(cascade.handler)); diff --git a/webdev/lib/src/webdev.dart b/webdev/lib/src/webdev.dart new file mode 100644 index 000000000..c9a467b27 --- /dev/null +++ b/webdev/lib/src/webdev.dart @@ -0,0 +1,84 @@ +// Copyright (c) 2019, 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. + +import 'dart:async'; + +import 'package:build_daemon/data/build_status.dart'; +import 'package:shelf/shelf.dart'; +import 'package:vm_service_lib/vm_service_lib.dart'; +import 'package:webdev/src/serve/handlers/dev_handler.dart'; + +import 'command/configuration.dart'; +import 'serve/chrome.dart'; +import 'serve/debugger/app_debug_services.dart'; +import 'serve/debugger/devtools.dart'; +import 'serve/injected/configuration.dart'; +import 'serve/webdev_server.dart'; + +Stream connectToWebdev( + int port, + int assetPort, + String target, + Stream buildResults, { + Handler optionalHandler, +}) async* { + var hostname = 'localhost'; + var configuration = Configuration( + hostname: hostname, + requireBuildWebCompilers: false, + debug: true, + autoRun: true, + reload: ReloadConfiguration.none, + ); + var devtools = await DevTools.start(hostname); + var serverOptions = ServerOptions( + configuration, + port, + target, + assetPort, + optionalHandler: optionalHandler, + ); + var webDevServer = + await WebDevServer.start(serverOptions, buildResults, devtools); + var chrome = await Chrome.start( + ['http://${webDevServer.host}:${webDevServer.port}/'], + port: configuration.chromeDebugPort); + var devHandler = webDevServer.devHandler; + await for (var connection in devHandler.connectedApps) { + var appDebugServices = await devHandler.loadAppServices( + connection.request.appId, connection.request.instanceId); + yield WebDevHandle( + appDebugServices, connection, chrome, webDevServer, devtools); + } +} + +class WebDevHandle { + final AppDebugServices _appDebugServices; + final DevConnection _devConnection; + final Chrome _chrome; + final WebDevServer _webDevServer; + final DevTools _devTools; + + WebDevHandle(this._appDebugServices, this._devConnection, this._chrome, + this._webDevServer, this._devTools); + + Future close() async { + await _webDevServer.stop(); + await _chrome.close(); + await _devTools.close(); + await _appDebugServices.close(); + } + + VmService get vmService { + return _appDebugServices.webdevClient.client; + } + + Stream get onTabClose { + return _appDebugServices.chromeProxyService.tabConnection.onClose; + } + + Uri get wsUri => Uri.parse(_appDebugServices.debugService.wsUri); + + void runMain() => _devConnection.runMain(); +}