// Copyright 2013 The Flutter 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 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:isolate';
import 'dart:math';

import 'package:async/async.dart';
import 'package:http_multi_server/http_multi_server.dart';
import 'package:image/image.dart';
import 'package:package_config/package_config.dart';
import 'package:path/path.dart' as p;
import 'package:pool/pool.dart';
import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:shelf_packages_handler/shelf_packages_handler.dart';
import 'package:shelf_static/shelf_static.dart';
import 'package:shelf_web_socket/shelf_web_socket.dart';
import 'package:skia_gold_client/skia_gold_client.dart';
import 'package:stream_channel/stream_channel.dart';

import 'package:test_api/src/backend/runtime.dart';
import 'package:test_api/src/backend/suite_platform.dart';
import 'package:test_core/src/runner/configuration.dart';
import 'package:test_core/src/runner/environment.dart';
import 'package:test_core/src/runner/platform.dart';
import 'package:test_core/src/runner/plugin/platform_helpers.dart';
import 'package:test_core/src/runner/runner_suite.dart';
import 'package:test_core/src/runner/suite.dart';
import 'package:test_core/src/util/io.dart';
import 'package:test_core/src/util/stack_trace_mapper.dart';

import 'package:web_socket_channel/web_socket_channel.dart';
import 'package:web_test_utils/goldens.dart';
import 'package:web_test_utils/image_compare.dart';

import 'browser.dart';
import 'common.dart';
import 'environment.dart' as env;

/// Custom test platform that serves web engine unit tests.
class BrowserPlatform extends PlatformPlugin {
  /// Starts the server.
  ///
  /// [browserEnvironment] provides the browser environment to run the test.
  ///
  /// If [doUpdateScreenshotGoldens] is true updates screenshot golden files
  /// instead of failing the test on screenshot mismatches.
  static Future<BrowserPlatform> start({
    required BrowserEnvironment browserEnvironment,
    required bool doUpdateScreenshotGoldens,
    required SkiaGoldClient? skiaClient,
    required String? overridePathToCanvasKit,
  }) async {
    final shelf_io.IOServer server =
        shelf_io.IOServer(await HttpMultiServer.loopback(0));
    return BrowserPlatform._(
      browserEnvironment: browserEnvironment,
      server: server,
      isDebug: Configuration.current.pauseAfterLoad,
      doUpdateScreenshotGoldens: doUpdateScreenshotGoldens,
      packageConfig: await loadPackageConfigUri((await Isolate.packageConfig)!),
      skiaClient: skiaClient,
      overridePathToCanvasKit: overridePathToCanvasKit,
    );
  }

  /// If true, runs the browser with a visible windows (i.e. not headless) and
  /// pauses before running the tests to give the developer a chance to set
  /// breakpoints in the code.
  final bool isDebug;

  /// The underlying server.
  final shelf.Server server;

  /// Provides the environment for the browser running tests.
  final BrowserEnvironment browserEnvironment;

  /// The URL for this server.
  Uri get url => server.url.resolve('/');

  /// A [OneOffHandler] for servicing WebSocket connections for
  /// [BrowserManager]s.
  ///
  /// This is one-off because each [BrowserManager] can only connect to a single
  /// WebSocket,
  final OneOffHandler _webSocketHandler = OneOffHandler();

  /// Whether [close] has been called.
  bool get _closed => _closeMemo.hasRun;

  /// Whether to update screenshot golden files.
  final bool doUpdateScreenshotGoldens;

  late final shelf.Handler _packageUrlHandler = packagesDirHandler();

  final PackageConfig packageConfig;

  /// A client for communicating with the Skia Gold backend to fetch, compare
  /// and update images.
  final SkiaGoldClient? skiaClient;

  final String? overridePathToCanvasKit;

  BrowserPlatform._({
    required this.browserEnvironment,
    required this.server,
    required this.isDebug,
    required this.doUpdateScreenshotGoldens,
    required this.packageConfig,
    required this.skiaClient,
    required this.overridePathToCanvasKit,
  }) {
    // The cascade of request handlers.
    final shelf.Cascade cascade = shelf.Cascade()
        // The web socket that carries the test channels for running tests and
        // reporting restuls. See [_browserManagerFor] and [BrowserManager.start]
        // for details on how the channels are established.
        .add(_webSocketHandler.handler)

        // Serves /packages/* requests; fetches files and sources from
        // pubspec dependencies.
        //
        // Includes:
        //  * Requests for Dart sources from source maps
        //  * Assets that are part of the engine sources, such as Ahem.ttf
        .add(_packageUrlHandler)
        .add(_canvasKitOverrideHandler)

        // Serves files from the web_ui/build/ directory at the root (/) URL path.
        .add(buildDirectoryHandler)
        .add(_testImageListingHandler)

        // Serves the initial HTML for the test.
        .add(_testBootstrapHandler)

        // Serves files from the root of web_ui.
        //
        // This is needed because sourcemaps refer to local files, i.e. those
        // that don't come from package dependencies, relative to web_ui/.
        //
        // Examples of URLs that this handles:
        //  * /test/alarm_clock_test.dart
        //  * /lib/src/engine/alarm_clock.dart
        .add(createStaticHandler(env.environment.webUiRootDir.path))

        // Serves absolute package URLs (i.e. not /packages/* but /Users/user/*/hosted/pub.dartlang.org/*).
        // This handler goes last, after all more specific handlers failed to handle the request.
        .add(_createAbsolutePackageUrlHandler())
        .add(_screenshotHandler)
        .add(_fileNotFoundCatcher);

    server.mount(cascade.handler);
  }

  /// If a path to a custom local build of CanvasKit was specified, serve from
  /// there instead of serving the default CanvasKit in the build/ directory.
  Future<shelf.Response> _canvasKitOverrideHandler(
      shelf.Request request) async {
    final String? pathOverride = overridePathToCanvasKit;

    if (pathOverride == null || !request.url.path.startsWith('canvaskit/')) {
      return shelf.Response.notFound('Not a request for CanvasKit.');
    }

    final File file = File(p.joinAll(<String>[
      pathOverride,
      ...p.split(request.url.path).skip(1),
    ]));

    if (!file.existsSync()) {
      return shelf.Response.notFound('File not found: ${request.url.path}');
    }

    final String extension = p.extension(file.path);
    final String? contentType = contentTypes[extension];

    if (contentType == null) {
      final String error =
          'Failed to determine Content-Type for "${request.url.path}".';
      stderr.writeln(error);
      return shelf.Response.internalServerError(body: error);
    }

    return shelf.Response.ok(
      file.readAsBytesSync(),
      headers: <String, Object>{
        HttpHeaders.contentTypeHeader: contentType,
      },
    );
  }

  /// Lists available test images under `web_ui/build/test_images`.
  Future<shelf.Response> _testImageListingHandler(shelf.Request request) async {
    const Map<String, String> supportedImageTypes = <String, String>{
      '.png': 'image/png',
      '.jpg': 'image/jpeg',
      '.jpeg': 'image/jpeg',
      '.gif': 'image/gif',
      '.webp': 'image/webp',
      '.bmp': 'image/bmp',
    };

    if (request.url.path != 'test_images/') {
      return shelf.Response.notFound('Not found.');
    }

    final Directory testImageDirectory = Directory(p.join(
      env.environment.webUiBuildDir.path,
      'test_images',
    ));

    final List<String> testImageFiles = testImageDirectory
        .listSync(recursive: true)
        .whereType<File>()
        .map<String>(
            (File file) => p.relative(file.path, from: testImageDirectory.path))
        .where(
            (String path) => supportedImageTypes.containsKey(p.extension(path)))
        .toList();

    return shelf.Response.ok(
      json.encode(testImageFiles),
      headers: <String, Object>{
        HttpHeaders.contentTypeHeader: 'application/json',
      },
    );
  }

  Future<shelf.Response> _fileNotFoundCatcher(shelf.Request request) async {
    print('HTTP 404: ${request.url}');
    return shelf.Response.notFound('File not found');
  }

  /// Handles URLs pointing to Dart sources using absolute URI paths.
  ///
  /// Dart source paths that dart2js puts in source maps for pub packages are
  /// relative to the source map file. Example:
  ///
  ///     ../../../../../../../../../Users/yegor/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/stack_trace-1.10.0/lib/src/frame.dart
  ///
  /// When the browser requests the file from the source map it sends a GET
  /// request like this:
  ///
  ///     GET /Users/yegor/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/stack_trace-1.10.0/lib/src/frame.dart
  ///
  /// There's no predictable structure in this URL. It's unclear whether this
  /// is a request for a source file, or someone trying to hack your
  /// workstation.
  ///
  /// This handler treats the URL as an absolute path, but instead of
  /// unconditionally serving it, it first checks with `package_config.json` on
  /// whether this is a request for a Dart source that's listed in pubspec
  /// dependencies. For example, the `stack_trace` package would be listed in
  /// `package_config.json` as:
  ///
  ///     file:///C:/Users/yegor/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/stack_trace-1.10.0
  ///
  /// If the requested URL points into one of the packages in the package config,
  /// the file is served. Otherwise, HTTP 404 is returned without file contents.
  ///
  /// To handle drive letters (C:\) and *nix file system roots, the URL and
  /// package paths are initially stripped of the root and compared to each
  /// other as prefixes. To actually read the file, the file system root is
  /// prepended before creating the file.
  shelf.Handler _createAbsolutePackageUrlHandler() {
    final Map<String, Package> urlToPackage = <String, Package>{};
    for (final Package package in packageConfig.packages) {
      // Turns the URI as encoded in package_config.json to a file path.
      final String configPath = p.fromUri(package.root);

      // Strips drive letter and root prefix, if any, for example:
      //
      // C:\Users\user\AppData => Users\user\AppData
      // /home/user/path.dart => home/user/path.dart
      final String rootRelativePath =
          p.relative(configPath, from: p.rootPrefix(configPath));
      urlToPackage[p.toUri(rootRelativePath).path] = package;
    }
    return (shelf.Request request) async {
      final String requestedPath = request.url.path;
      // The cast is needed because keys are non-null String, so there's no way
      // to return null for a mismatch.
      final String? packagePath = urlToPackage.keys.cast<String?>().firstWhere(
            (String? packageUrl) => requestedPath.startsWith(packageUrl!),
            orElse: () => null,
          );
      if (packagePath == null) {
        return shelf.Response.notFound('Not a pub.dartlang.org request');
      }

      // Attach the root prefix, such as drive letter, and convert from URI to path.
      // Examples:
      //
      // Users\user\AppData => C:\Users\user\AppData
      // home/user/path.dart => /home/user/path.dart
      final Package package = urlToPackage[packagePath]!;
      final String filePath = p.join(
        p.rootPrefix(p.fromUri(package.root.path)),
        p.fromUri(requestedPath),
      );
      final File fileInPackage = File(filePath);
      if (!fileInPackage.existsSync()) {
        return shelf.Response.notFound('File not found: $requestedPath');
      }
      return shelf.Response.ok(fileInPackage.openRead());
    };
  }

  Future<shelf.Response> _screenshotHandler(shelf.Request request) async {
    if (!request.requestedUri.path.endsWith('/screenshot')) {
      return shelf.Response.notFound(
          'This request is not handled by the screenshot handler');
    }

    final String payload = await request.readAsString();
    final Map<String, dynamic> requestData =
        json.decode(payload) as Map<String, dynamic>;
    final String filename = requestData['filename'] as String;

    if (!(await browserManager).supportsScreenshots) {
      print(
        'INFO: Skipping screenshot check for $filename. Current browser/OS '
        'combination does not support screenshots.',
      );
      return shelf.Response.ok(json.encode('OK'));
    }

    final bool write = requestData['write'] as bool;
    final double maxDiffRate = requestData.containsKey('maxdiffrate')
        ? (requestData['maxdiffrate'] as num)
            .toDouble() // can be parsed as either int or double
        : kMaxDiffRateFailure;
    final Map<String, dynamic> region =
        requestData['region'] as Map<String, dynamic>;
    final PixelComparison pixelComparison = PixelComparison.values.firstWhere(
        (PixelComparison value) =>
            value.toString() == requestData['pixelComparison']);
    final bool isCanvaskitTest = requestData['isCanvaskitTest'] as bool;
    final String result = await _diffScreenshot(
        filename, write, maxDiffRate, region, pixelComparison, isCanvaskitTest);
    return shelf.Response.ok(json.encode(result));
  }

  Future<String> _diffScreenshot(
    String filename,
    bool write,
    double maxDiffRateFailure,
    Map<String, dynamic> region,
    PixelComparison pixelComparison,
    bool isCanvaskitTest,
  ) async {
    if (doUpdateScreenshotGoldens) {
      write = true;
    }

    final Rectangle<num> regionAsRectange = Rectangle<num>(
      region['x'] as num,
      region['y'] as num,
      region['width'] as num,
      region['height'] as num,
    );

    // Take screenshot.
    final Image screenshot =
        await (await browserManager).captureScreenshot(regionAsRectange);

    return compareImage(
      screenshot,
      doUpdateScreenshotGoldens,
      filename,
      pixelComparison,
      maxDiffRateFailure,
      skiaClient,
      isCanvaskitTest: isCanvaskitTest,
    );
  }

  static const Map<String, String> contentTypes = <String, String>{
    '.js': 'text/javascript',
    '.wasm': 'application/wasm',
    '.html': 'text/html',
    '.htm': 'text/html',
    '.css': 'text/css',
    '.ico': 'image/icon-x',
    '.png': 'image/png',
    '.jpg': 'image/jpeg',
    '.jpeg': 'image/jpeg',
    '.gif': 'image/gif',
    '.webp': 'image/webp',
    '.bmp': 'image/bmp',
    '.svg': 'image/svg+xml',
    '.json': 'application/json',
    '.ttf': 'font/ttf',
    '.woff': 'font/woff',
    '.woff2': 'font/woff2',
  };

  /// A simple file handler that serves files whose URLs and paths are
  /// statically known.
  ///
  /// This is used for trivial use-cases, such as `favicon.ico`, host pages, etc.
  shelf.Response buildDirectoryHandler(shelf.Request request) {
    final File fileInBuild = File(p.join(
      env.environment.webUiBuildDir.path,
      request.url.path,
    ));

    if (!fileInBuild.existsSync()) {
      return shelf.Response.notFound('File not found: ${request.url.path}');
    }

    final String extension = p.extension(fileInBuild.path);
    final String? contentType = contentTypes[extension];

    if (contentType == null) {
      final String error =
          'Failed to determine Content-Type for "${request.url.path}".';
      stderr.writeln(error);
      return shelf.Response.internalServerError(body: error);
    }

    return shelf.Response.ok(
      fileInBuild.readAsBytesSync(),
      headers: <String, Object>{
        HttpHeaders.contentTypeHeader: contentType,
      },
    );
  }

  /// Serves the HTML file that bootstraps the test.
  shelf.Response _testBootstrapHandler(shelf.Request request) {
    final String path = p.fromUri(request.url);

    if (path.endsWith('.html')) {
      final String test = p.withoutExtension(path) + '.dart';

      // Link to the Dart wrapper.
      final String scriptBase = htmlEscape.convert(p.basename(test));
      final String link = '<link rel="x-dart-test" href="$scriptBase">';

      return shelf.Response.ok('''
        <!DOCTYPE html>
        <html>
        <head>
          <title>${htmlEscape.convert(test)} Test</title>
          <meta name="assetBase" content="/">
          <script>
            window.flutterConfiguration = {
              canvasKitBaseUrl: "/canvaskit/"
            };
          </script>
          $link
          <script src="packages/test/dart.js"></script>
        </head>
        </html>
      ''', headers: <String, String>{'Content-Type': 'text/html'});
    }

    return shelf.Response.notFound('Not found.');
  }

  void _checkNotClosed() {
    if (_closed) {
      throw StateError('Cannot load test suite. Test platform is closed.');
    }
  }

  /// Loads the test suite at [path] on the platform [platform].
  ///
  /// This will start a browser to load the suite if one isn't already running.
  /// Throws an [ArgumentError] if `platform.platform` isn't a browser.
  @override
  Future<RunnerSuite> load(String path, SuitePlatform platform,
      SuiteConfiguration suiteConfig, Object message) async {
    _checkNotClosed();
    if (suiteConfig.precompiledPath == null) {
      throw Exception('This test platform only supports precompiled JS.');
    }
    final Runtime browser = platform.runtime;
    assert(suiteConfig.runtimes.contains(browser.identifier));

    if (!browser.isBrowser) {
      throw ArgumentError('$browser is not a browser.');
    }
    _checkNotClosed();

    final Uri suiteUrl = url.resolveUri(p.toUri(p.withoutExtension(
            p.relative(path, from: env.environment.webUiBuildDir.path)) +
        '.html'));
    _checkNotClosed();

    final BrowserManager? browserManager = await _startBrowserManager();
    if (browserManager == null) {
      throw StateError(
          'Failed to initialize browser manager for ${browserEnvironment.name}');
    }
    _checkNotClosed();

    final RunnerSuite suite =
        await browserManager.load(path, suiteUrl, suiteConfig, message);
    _checkNotClosed();
    return suite;
  }

  @override
  StreamChannel<dynamic> loadChannel(String path, SuitePlatform platform) =>
      throw UnimplementedError();

  Future<BrowserManager?>? _browserManager;
  Future<BrowserManager> get browserManager async => (await _browserManager!)!;

  /// Starts a browser manager for the browser provided by [browserEnvironment];
  ///
  /// If no browser manager is running yet, starts one.
  Future<BrowserManager?> _startBrowserManager() {
    if (_browserManager != null) {
      return _browserManager!;
    }

    final Completer<WebSocketChannel> completer =
        Completer<WebSocketChannel>.sync();
    final String path =
        _webSocketHandler.create(webSocketHandler(completer.complete));
    final Uri webSocketUrl = url.replace(scheme: 'ws').resolve(path);
    final Uri hostUrl = url.resolve('host/index.html').replace(
        queryParameters: <String, dynamic>{
          'managerUrl': webSocketUrl.toString(),
          'debug': isDebug.toString()
        });

    final Future<BrowserManager?> future = BrowserManager.start(
      browserEnvironment: browserEnvironment,
      url: hostUrl,
      future: completer.future,
      packageConfig: packageConfig,
      debug: isDebug,
    );

    // Store null values for browsers that error out so we know not to load them
    // again.
    _browserManager = future.catchError((dynamic _) => null);

    return future;
  }

  /// Close all the browsers that the server currently has open.
  ///
  /// Note that this doesn't close the server itself. Browser tests can still be
  /// loaded, they'll just spawn new browsers.
  @override
  Future<void> closeEphemeral() async {
    if (_browserManager != null) {
      final BrowserManager? result = await _browserManager!;
      await result?.close();
    }
  }

  /// Closes the server and releases all its resources.
  ///
  /// Returns a [Future] that completes once the server is closed and its
  /// resources have been fully released.
  @override
  Future<void> close() {
    return _closeMemo.runOnce(() async {
      final List<Future<void>> futures = <Future<void>>[];
      futures.add(Future<void>.microtask(() async {
        if (_browserManager != null) {
          final BrowserManager? result = await _browserManager!;
          await result?.close();
        }
      }));
      futures.add(server.close());

      await Future.wait(futures);
    });
  }

  final AsyncMemoizer<dynamic> _closeMemo = AsyncMemoizer<dynamic>();
}

/// A Shelf handler that provides support for one-time handlers.
///
/// This is useful for handlers that only expect to be hit once before becoming
/// invalid and don't need to have a persistent URL.
class OneOffHandler {
  /// A map from URL paths to handlers.
  final Map<String, shelf.Handler> _handlers = <String, shelf.Handler>{};

  /// The counter of handlers that have been activated.
  int _counter = 0;

  /// The actual [shelf.Handler] that dispatches requests.
  shelf.Handler get handler => _onRequest;

  /// Creates a new one-off handler that forwards to [handler].
  ///
  /// Returns a string that's the URL path for hitting this handler, relative to
  /// the URL for the one-off handler itself.
  ///
  /// [handler] will be unmounted as soon as it receives a request.
  String create(shelf.Handler handler) {
    final String path = _counter.toString();
    _handlers[path] = handler;
    _counter++;
    return path;
  }

  /// Dispatches [request] to the appropriate handler.
  FutureOr<shelf.Response> _onRequest(shelf.Request request) {
    final List<String> components = p.url.split(request.url.path);
    if (components.isEmpty) {
      return shelf.Response.notFound(null);
    }

    final String path = components.removeAt(0);
    final shelf.Handler? handler = _handlers.remove(path);
    if (handler == null) {
      return shelf.Response.notFound(null);
    }
    return handler(request.change(path: path));
  }
}

/// Manages the connection to a single running browser.
///
/// This is in charge of telling the browser which test suites to load and
/// converting its responses into [Suite] objects.
class BrowserManager {
  final PackageConfig packageConfig;

  /// The browser instance that this is connected to via [_channel].
  final Browser _browser;

  /// The browser environment for this test.
  final BrowserEnvironment _browserEnvironment;

  /// The channel used to communicate with the browser.
  ///
  /// This is connected to a page running `static/host.dart`.
  late final MultiChannel<dynamic> _channel;

  /// A pool that ensures that limits the number of initial connections the
  /// manager will wait for at once.
  ///
  /// This isn't the *total* number of connections; any number of iframes may be
  /// loaded in the same browser. However, the browser can only load so many at
  /// once, and we want a timeout in case they fail so we only wait for so many
  /// at once.
  final Pool _pool = Pool(8);

  /// The ID of the next suite to be loaded.
  ///
  /// This is used to ensure that the suites can be referred to consistently
  /// across the client and server.
  int _suiteID = 0;

  /// Whether the channel to the browser has closed.
  bool _closed = false;

  /// The completer for [_BrowserEnvironment.displayPause].
  ///
  /// This will be `null` as long as the browser isn't displaying a pause
  /// screen.
  CancelableCompleter<void>? _pauseCompleter;

  /// The controller for [_BrowserEnvironment.onRestart].
  final StreamController<dynamic> _onRestartController =
      StreamController<dynamic>.broadcast();

  /// The environment to attach to each suite.
  late final Future<_BrowserEnvironment> _environment;

  /// Controllers for every suite in this browser.
  ///
  /// These are used to mark suites as debugging or not based on the browser's
  /// pings.
  final Set<RunnerSuiteController> _controllers = <RunnerSuiteController>{};

  // A timer that's reset whenever we receive a message from the browser.
  //
  // Because the browser stops running code when the user is actively debugging,
  // this lets us detect whether they're debugging reasonably accurately.
  late final RestartableTimer _timer;

  /// Starts the browser identified by [runtime] and has it connect to [url].
  ///
  /// [url] should serve a page that establishes a WebSocket connection with
  /// this process. That connection, once established, should be emitted via
  /// [future]. If [debug] is true, starts the browser in debug mode, with its
  /// debugger interfaces on and detected.
  ///
  /// The [settings] indicate how to invoke this browser's executable.
  ///
  /// Returns the browser manager, or throws an [Exception] if a
  /// connection fails to be established.
  static Future<BrowserManager?> start({
    required BrowserEnvironment browserEnvironment,
    required Uri url,
    required Future<WebSocketChannel> future,
    required PackageConfig packageConfig,
    bool debug = false,
  }) async {
    final Browser browser =
        await _newBrowser(url, browserEnvironment, debug: debug);
    return _startBrowserManager(
        browserEnvironment: browserEnvironment,
        url: url,
        future: future,
        packageConfig: packageConfig,
        browser: browser,
        debug: debug);
  }

  static Future<BrowserManager?> _startBrowserManager({
    required BrowserEnvironment browserEnvironment,
    required Uri url,
    required Future<WebSocketChannel> future,
    required PackageConfig packageConfig,
    required Browser browser,
    bool debug = false,
  }) {
    final Completer<BrowserManager> completer = Completer<BrowserManager>();

    // For the cases where we use a delegator such as `adb` (for Android) or
    // `xcrun` (for IOS), these delegator processes can shut down before the
    // websocket is available. Therefore do not throw an error if process
    // exits with exitCode 0. Note that `browser` will throw and error if the
    // exit code was not 0, which will be processed by the next callback.
    browser.onExit.catchError((Object error, StackTrace stackTrace) {
      if (completer.isCompleted) {
        return;
      }
      completer.completeError(error, stackTrace);
    });

    future.then((WebSocketChannel webSocket) {
      if (completer.isCompleted) {
        return;
      }
      completer.complete(BrowserManager._(
          packageConfig, browser, browserEnvironment, webSocket));
    }).catchError((Object error, StackTrace stackTrace) {
      browser.close();
      if (completer.isCompleted) {
        return null;
      }
      completer.completeError(error, stackTrace);
    });

    return completer.future;
  }

  /// Starts the browser and requests that it load the test page at [url].
  ///
  /// If [debug] is true, starts the browser in debug mode.
  static Future<Browser> _newBrowser(
      Uri url, BrowserEnvironment browserEnvironment,
      {bool debug = false}) {
    return browserEnvironment.launchBrowserInstance(url, debug: debug);
  }

  /// Creates a new BrowserManager that communicates with the browser over
  /// [webSocket].
  BrowserManager._(this.packageConfig, this._browser, this._browserEnvironment,
      WebSocketChannel webSocket) {
    // The duration should be short enough that the debugging console is open as
    // soon as the user is done setting breakpoints, but long enough that a test
    // doing a lot of synchronous work doesn't trigger a false positive.
    //
    // Start this canceled because we don't want it to start ticking until we
    // get some response from the iframe.
    _timer = RestartableTimer(const Duration(seconds: 3), () {
      for (final RunnerSuiteController controller in _controllers) {
        controller.setDebugging(true);
      }
    })
      ..cancel();

    // Whenever we get a message, no matter which child channel it's for, we the
    // know browser is still running code which means the user isn't debugging.
    _channel = MultiChannel<dynamic>(webSocket
        .cast<String>()
        .transform(jsonDocument)
        .changeStream((Stream<Object?> stream) {
      return stream.map((Object? message) {
        if (!_closed) {
          _timer.reset();
        }
        for (final RunnerSuiteController controller in _controllers) {
          controller.setDebugging(false);
        }

        return message;
      });
    }));

    _environment = _loadBrowserEnvironment();
    _channel.stream.listen(
        (dynamic message) => _onMessage(message as Map<dynamic, dynamic>),
        onDone: close);
  }

  /// Loads [_BrowserEnvironment].
  Future<_BrowserEnvironment> _loadBrowserEnvironment() async {
    return _BrowserEnvironment(this, await _browser.observatoryUrl,
        await _browser.remoteDebuggerUrl, _onRestartController.stream);
  }

  /// Tells the browser the load a test suite from the URL [url].
  ///
  /// [url] should be an HTML page with a reference to the JS-compiled test
  /// suite. [path] is the path of the original test suite file, which is used
  /// for reporting. [suiteConfig] is the configuration for the test suite.
  Future<RunnerSuite> load(String path, Uri url, SuiteConfiguration suiteConfig,
      Object message) async {
    url = url.replace(
        fragment: Uri.encodeFull(jsonEncode(<String, dynamic>{
      'metadata': suiteConfig.metadata.serialize(),
      'browser': _browserEnvironment.packageTestRuntime.identifier
    })));

    final int suiteID = _suiteID++;
    RunnerSuiteController? controller;
    void closeIframe() {
      if (_closed) {
        return;
      }
      _controllers.remove(controller);
      _channel.sink
          .add(<String, dynamic>{'command': 'closeSuite', 'id': suiteID});
    }

    // The virtual channel will be closed when the suite is closed, in which
    // case we should unload the iframe.
    final VirtualChannel<dynamic> virtualChannel = _channel.virtualChannel();
    final int suiteChannelID = virtualChannel.id;
    final StreamChannel<dynamic> suiteChannel = virtualChannel.transformStream(
        StreamTransformer<dynamic, dynamic>.fromHandlers(
            handleDone: (EventSink<dynamic> sink) {
      closeIframe();
      sink.close();
    }));

    return _pool.withResource<RunnerSuite>(() async {
      _channel.sink.add(<String, dynamic>{
        'command': 'loadSuite',
        'url': url.toString(),
        'id': suiteID,
        'channel': suiteChannelID
      });

      try {
        controller = deserializeSuite(
            path,
            currentPlatform(_browserEnvironment.packageTestRuntime),
            suiteConfig,
            await _environment,
            suiteChannel,
            message);

        final String sourceMapFileName =
            '${p.basename(path)}.browser_test.dart.js.map';
        final String pathToTest = p.dirname(path);

        final String mapPath = p.join(env.environment.webUiRootDir.path,
            'build', pathToTest, sourceMapFileName);

        final Map<String, Uri> packageMap = <String, Uri>{
          for (Package p in packageConfig.packages) p.name: p.packageUriRoot
        };
        final JSStackTraceMapper mapper = JSStackTraceMapper(
          await File(mapPath).readAsString(),
          mapUrl: p.toUri(mapPath),
          packageMap: packageMap,
          sdkRoot: p.toUri(sdkDir),
        );

        controller!.channel('test.browser.mapper').sink.add(mapper.serialize());

        _controllers.add(controller!);
        return await controller!.suite;
      } catch (_) {
        closeIframe();
        rethrow;
      }
    });
  }

  /// An implementation of [Environment.displayPause].
  CancelableOperation<void> _displayPause() {
    CancelableCompleter<void>? pauseCompleter = _pauseCompleter;
    if (pauseCompleter != null) {
      return pauseCompleter.operation;
    }

    pauseCompleter = CancelableCompleter<void>(onCancel: () {
      _channel.sink.add(<String, String>{'command': 'resume'});
      _pauseCompleter = null;
    });
    _pauseCompleter = pauseCompleter;

    pauseCompleter.operation.value.whenComplete(() {
      _pauseCompleter = null;
    });

    _channel.sink.add(<String, String>{'command': 'displayPause'});

    return pauseCompleter.operation;
  }

  /// The callback for handling messages received from the host page.
  void _onMessage(Map<dynamic, dynamic> message) {
    switch (message['command'] as String) {
      case 'ping':
        break;

      case 'restart':
        _onRestartController.add(null);
        break;

      case 'resume':
        _pauseCompleter?.complete();
        break;

      default:
        // Unreachable.
        assert(false);
        break;
    }
  }

  bool get supportsScreenshots => _browser.supportsScreenshots;

  Future<Image> captureScreenshot(Rectangle<num> region) =>
      _browser.captureScreenshot(region);

  /// Closes the manager and releases any resources it owns, including closing
  /// the browser.
  Future<void> close() => _closeMemoizer.runOnce(() {
        _closed = true;
        _timer.cancel();
        _pauseCompleter?.complete();
        _pauseCompleter = null;
        _controllers.clear();
        return _browser.close();
      });
  final AsyncMemoizer<dynamic> _closeMemoizer = AsyncMemoizer<dynamic>();
}

/// An implementation of [Environment] for the browser.
///
/// All methods forward directly to [BrowserManager].
class _BrowserEnvironment implements Environment {
  final BrowserManager _manager;

  @override
  final bool supportsDebugging = true;

  @override
  final Uri? observatoryUrl;

  @override
  final Uri? remoteDebuggerUrl;

  @override
  final Stream<dynamic> onRestart;

  _BrowserEnvironment(this._manager, this.observatoryUrl,
      this.remoteDebuggerUrl, this.onRestart);

  @override
  CancelableOperation<void> displayPause() => _manager._displayPause();
}

bool get isCirrus => Platform.environment['CIRRUS_CI'] == 'true';
