public async Task <IBrowser> ConnectAsync(string wsEndpoint, BrowserTypeConnectOptions options = null)
        {
            options ??= new BrowserTypeConnectOptions();
            var headers = new List <KeyValuePair <string, string> >(options.Headers ?? new Dictionary <string, string>())
            {
                new KeyValuePair <string, string>("x-playwright-browser", Name),
            }.ToDictionary(pair => pair.Key, pair => pair.Value);
            JsonPipe pipe = (await _channel.ConnectAsync(wsEndpoint: wsEndpoint, headers: headers, slowMo: options.SlowMo, timeout: options.Timeout).ConfigureAwait(false)).Object;

            void ClosePipe()
            {
                pipe.CloseAsync().IgnoreException();
            }

#pragma warning disable CA2000 // Dispose objects before losing scope
            var connection = new Connection();
#pragma warning restore CA2000
            connection.MarkAsRemote();
            connection.Close += (_, _) => ClosePipe();

            string  closeError = null;
            Browser browser    = null;
            void OnPipeClosed()
            {
                // Emulate all pages, contexts and the browser closing upon disconnect.
                foreach (BrowserContext context in browser?.BrowserContextsList.ToArray() ?? Array.Empty <BrowserContext>())
                {
                    foreach (Page page in context.PagesList.ToArray())
                    {
                        page.OnClose();
                    }
                    context.OnClose();
                }
                browser?.DidClose();
                connection.DoClose(closeError != null ? closeError : DriverMessages.BrowserClosedExceptionMessage);
            }

            pipe.Closed         += (_, _) => OnPipeClosed();
            connection.OnMessage = async(object message) =>
            {
                try
                {
                    await pipe.SendAsync(message).ConfigureAwait(false);
                }
                catch (Exception e) when(DriverMessages.IsSafeCloseError(e))
                {
                    // swallow exception
                }
                catch
                {
                    OnPipeClosed();
                }
            };

            pipe.Message += (_, message) =>
            {
                try
                {
                    connection.Dispatch(message);
                }
                catch (Exception ex)
                {
                    closeError = ex.ToString();
                    _channel.Connection.TraceMessage("pw:dotnet", $"Dispatching error: {ex.Message}\n{ex.StackTrace}");
                    ClosePipe();
                }
            };

            async Task <IBrowser> CreateBrowserAsync()
            {
                var playwright = await connection.InitializePlaywrightAsync().ConfigureAwait(false);

                playwright.Connection = connection;
                if (playwright.PreLaunchedBrowser == null)
                {
                    ClosePipe();
                    throw new ArgumentException("Malformed endpoint. Did you use launchServer method?");
                }
                browser = playwright.PreLaunchedBrowser;
                browser.ShouldCloseConnectionOnClose = true;
                browser.Disconnected += (_, _) => ClosePipe();
                browser.LocalUtils    = Playwright.Utils;
                return(playwright.PreLaunchedBrowser);
            }

            var task    = CreateBrowserAsync();
            var timeout = options?.Timeout != null ? (int)options.Timeout : 30_000;
            return(await task.WithTimeout(timeout, _ => throw new TimeoutException($"BrowserType.ConnectAsync: Timeout {options.Timeout}ms exceeded")).ConfigureAwait(false));
        }
Example #2
0
 /// <inheritdoc />
 public async Task <IBrowser> ConnectAsync(ConnectOptions options = null)
 => (await _channel.ConnectAsync(options).ConfigureAwait(false)).Object;