// 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: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,
  }) async {
    final shelf_io.IOServer server = shelf_io.IOServer(await HttpMultiServer.loopback(0));
    return BrowserPlatform._(
      browserEnvironment: browserEnvironment,
      server: server,
      isDebug: Configuration.current.pauseAfterLoad,
      faviconPath: p.fromUri(await Isolate.resolvePackageUri(
          Uri.parse('package:test/src/runner/browser/static/favicon.ico'))),
      doUpdateScreenshotGoldens: doUpdateScreenshotGoldens,
      packageConfig: await loadPackageConfigUri((await Isolate.packageConfig)!),
    );
  }

  /// 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();

  /// Handles taking screenshots during tests.
  ///
  /// Implementation will differ depending on the browser.
  ScreenshotManager? _screenshotManager;

  /// 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;

  BrowserPlatform._({
    required this.browserEnvironment,
    required this.server,
    required this.isDebug,
    required String faviconPath,
    required this.doUpdateScreenshotGoldens,
    required this.packageConfig,
  }) {
    // The cascade of request handlers.
    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 /favicon.ico
        .add(createFileHandler(faviconPath))

        // 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)

        // Serves files from the web_ui/build/ directory at the root (/) URL path.
        //
        // Includes:
        //  * Precompiles .js files for tests
        //  * Sourcemaps
        .add(createStaticHandler(env.environment.webUiBuildDir.path))

        // 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());

    _screenshotManager = browserEnvironment.getScreenshotManager();
    if (_screenshotManager != null) {
      cascade = cascade.add(_screeshotHandler);
    }

    server.mount(cascade.handler);
  }

  /// 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> _screeshotHandler(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;
    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 String result = await _diffScreenshot(
        filename, write, maxDiffRate, region, pixelComparison);
    return shelf.Response.ok(json.encode(result));
  }

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

    filename =
        filename.replaceAll('.png', '${_screenshotManager!.filenameSuffix}.png');

    String goldensDirectory;
    if (filename.startsWith('__local__')) {
      filename = filename.substring('__local__/'.length);
      goldensDirectory = p.join(
        env.environment.webUiRootDir.path,
        'test',
        'golden_files',
      );
    } else {
      goldensDirectory = p.join(
        env.environment.webUiGoldensRepositoryDirectory.path,
        'engine',
        'web',
      );
    }

    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 _screenshotManager!.capture(regionAsRectange);

    return compareImage(
        screenshot,
        doUpdateScreenshotGoldens,
        filename,
        pixelComparison,
        maxDiffRateFailure,
        goldensDirectory: goldensDirectory,
        write: write);
  }

  /// 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>
          $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 ${browser.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;

  /// 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('packages/web_engine_tester/static/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,
  }) {
    final Browser browser = _newBrowser(url, browserEnvironment, debug: debug);

    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 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;
    }
  }

  /// 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';
