/// <summary> /// Attaches Puppeteer to an existing Chromium instance. The browser will be closed when the Browser is disposed. /// </summary> /// <param name="options">Options for connecting.</param> /// <returns>A connected browser.</returns> public async Task <Browser> ConnectAsync(ConnectOptions options) { try { if (_chromiumLaunched) { throw new InvalidOperationException("Unable to create or connect to another chromium process"); } _chromiumLaunched = true; var connectionDelay = options.SlowMo; var keepAliveInterval = 0; _connection = await Connection.Create(options.BrowserWSEndpoint, connectionDelay, keepAliveInterval, _loggerFactory).ConfigureAwait(false); return(await Browser.CreateAsync(_connection, options.IgnoreHTTPSErrors, true, null, () => { try { var closeTask = _connection.SendAsync("Browser.close", null); } catch (Exception ex) { _logger.LogError(ex, ex.Message); } return null; }).ConfigureAwait(false)); } catch (Exception ex) { throw new Exception("Failed to create connection", ex); } }
/// <summary> /// Attaches Puppeteer to an existing Chromium instance. The browser will be closed when the Browser is disposed. /// </summary> /// <param name="options">Options for connecting.</param> /// <returns>A connected browser.</returns> public async Task <Browser> ConnectAsync(ConnectOptions options) { EnsureSingleLaunchOrConnect(); if (!string.IsNullOrEmpty(options.BrowserURL) && !string.IsNullOrEmpty(options.BrowserWSEndpoint)) { throw new PuppeteerException("Exactly one of browserWSEndpoint or browserURL must be passed to puppeteer.connect"); } try { var browserWSEndpoint = string.IsNullOrEmpty(options.BrowserURL) ? options.BrowserWSEndpoint : await GetWSEndpointAsync(options.BrowserURL).ConfigureAwait(false); var connection = await Connection.Create(browserWSEndpoint, options, _loggerFactory).ConfigureAwait(false); var response = await connection.SendAsync <GetBrowserContextsResponse>("Target.getBrowserContexts").ConfigureAwait(false); return(await Browser .CreateAsync(connection, response.BrowserContextIds, options.IgnoreHTTPSErrors, options.DefaultViewport, null) .ConfigureAwait(false)); } catch (Exception ex) { throw new ChromiumProcessException("Failed to create connection", ex); } }
/// <summary> /// The method launches a browser instance with given arguments. The browser will be closed when the Browser is disposed. /// </summary> /// <param name="options">Options for launching Chrome</param> /// <returns>A connected browser.</returns> /// <remarks> /// See <a href="https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/">this article</a> /// for a description of the differences between Chromium and Chrome. /// <a href="https://chromium.googlesource.com/chromium/src/+/lkcr/docs/chromium_browser_vs_google_chrome.md">This article</a> describes some differences for Linux users. /// </remarks> public async Task <Browser> LaunchAsync(LaunchOptions options) { if (_chromiumLaunched) { throw new InvalidOperationException("Unable to create or connect to another chromium process"); } _chromiumLaunched = true; var chromeArguments = InitChromeArgument(options); var chromeExecutable = options.ExecutablePath; if (string.IsNullOrEmpty(chromeExecutable)) { var browserFetcher = new BrowserFetcher(); chromeExecutable = browserFetcher.RevisionInfo(BrowserFetcher.DefaultRevision).ExecutablePath; } if (!File.Exists(chromeExecutable)) { throw new FileNotFoundException("Failed to launch chrome! path to executable does not exist", chromeExecutable); } _chromeProcess = CreateChromeProcess(options, chromeArguments, chromeExecutable); try { var connectionDelay = options.SlowMo; var browserWSEndpoint = await WaitForEndpoint(_chromeProcess, options.Timeout).ConfigureAwait(false); try { var keepAliveInterval = 0; _connection = await Connection .Create(browserWSEndpoint, connectionDelay, keepAliveInterval, _loggerFactory) .ConfigureAwait(false); var browser = await Browser.CreateAsync( _connection, Array.Empty <string>(), options.IgnoreHTTPSErrors, !options.AppMode, _chromeProcess, GracefullyCloseChrome ) .ConfigureAwait(false); await EnsureInitialPageAsync(browser).ConfigureAwait(false); return(browser); } catch (Exception ex) { throw new ChromeProcessException("Failed to create connection", ex); } } catch { KillChrome(); await _chromeCloseTcs.Task.ConfigureAwait(false); throw; } }
/// <summary> /// Attaches Puppeteer to an existing Chromium instance. The browser will be closed when the Browser is disposed. /// </summary> /// <param name="options">Options for connecting.</param> /// <returns>A connected browser.</returns> public async Task <Browser> ConnectAsync(ConnectOptions options) { try { if (_chromiumLaunched) { throw new InvalidOperationException("Unable to create or connect to another chromium process"); } _chromiumLaunched = true; var connectionDelay = options.SlowMo; var keepAliveInterval = options.KeepAliveInterval; _connection = await Connection.Create(options.BrowserWSEndpoint, connectionDelay, keepAliveInterval); return(await Browser.CreateAsync(_connection, options, null, () => { var closeTask = _connection.SendAsync("Browser.close", null); return null; })); } catch (Exception ex) { throw new Exception("Failed to create connection", ex); } }
/// <summary> /// The method launches a browser instance with given arguments. The browser will be closed when the Browser is disposed. /// </summary> /// <param name="options">Options for launching the browser</param> /// <returns>A connected browser.</returns> /// <remarks> /// See <a href="https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/">this article</a> /// for a description of the differences between Chromium and Chrome. /// <a href="https://chromium.googlesource.com/chromium/src/+/lkcr/docs/chromium_browser_vs_google_chrome.md">This article</a> describes some differences for Linux users. /// </remarks> public async Task <Browser> LaunchAsync(LaunchOptions options) { if (options == null) { throw new ArgumentNullException(nameof(options)); } EnsureSingleLaunchOrConnect(); _product = options.Product; var executable = await GetOrFetchBrowserExecutableAsync(options).ConfigureAwait(false); Process = options.Product switch { Product.Chrome => new ChromiumLauncher(executable, options), Product.Firefox => new FirefoxLauncher(executable, options), _ => throw new ArgumentException("Invalid product"), }; try { await Process.StartAsync().ConfigureAwait(false); try { var connection = await Connection .Create(Process.EndPoint, options, _loggerFactory) .ConfigureAwait(false); var browser = await Browser .CreateAsync(connection, Array.Empty <string>(), options.IgnoreHTTPSErrors, options.DefaultViewport, Process, options.TargetFilter) .ConfigureAwait(false); await browser.WaitForTargetAsync(t => t.Type == TargetType.Page).ConfigureAwait(false); return(browser); } catch (Exception ex) { throw new ProcessException("Failed to create connection", ex); } } catch { await Process.KillAsync().ConfigureAwait(false); throw; } }
/// <summary> /// The method launches a browser instance with given arguments. The browser will be closed when the Browser is disposed. /// </summary> /// <param name="options">Options for launching Chrome</param> /// <param name="chromiumRevision">The revision of Chrome to launch.</param> /// <returns>A connected browser.</returns> /// <remarks> /// See <a href="https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/">this article</a> /// for a description of the differences between Chromium and Chrome. /// <a href="https://chromium.googlesource.com/chromium/src/+/lkcr/docs/chromium_browser_vs_google_chrome.md">This article</a> describes some differences for Linux users. /// </remarks> public async Task <Browser> LaunchAsync(LaunchOptions options, int chromiumRevision) { if (_chromiumLaunched) { throw new InvalidOperationException("Unable to create or connect to another chromium process"); } _chromiumLaunched = true; var chromeArguments = InitChromeArgument(options); var chromeExecutable = options.ExecutablePath; if (string.IsNullOrEmpty(chromeExecutable)) { var downloader = Downloader.CreateDefault(); var revisionInfo = downloader.RevisionInfo(Downloader.CurrentPlatform, chromiumRevision); chromeExecutable = revisionInfo.ExecutablePath; } if (!File.Exists(chromeExecutable)) { throw new FileNotFoundException("Failed to launch chrome! path to executable does not exist", chromeExecutable); } CreateChromeProcess(options, chromeArguments, chromeExecutable); try { var connectionDelay = options.SlowMo; var browserWSEndpoint = await WaitForEndpoint(_chromeProcess, options.Timeout, options.DumpIO); var keepAliveInterval = options.KeepAliveInterval; _connection = await Connection.Create(browserWSEndpoint, connectionDelay, keepAliveInterval, _loggerFactory); _processLoaded = true; if (options.LogProcess) { _logger.LogInformation("Process Count: {ProcessCount}", Interlocked.Increment(ref _processCount)); } return(await Browser.CreateAsync(_connection, options, _chromeProcess, KillChrome)); } catch (Exception ex) { ForceKillChrome(); throw new ChromeProcessException("Failed to create connection", ex); } }
/// <summary> /// Attaches Puppeteer to an existing Chromium instance. The browser will be closed when the Browser is disposed. /// </summary> /// <param name="options">Options for connecting.</param> /// <returns>A connected browser.</returns> public async Task <Browser> ConnectAsync(ConnectOptions options) { EnsureSingleLaunchOrConnect(); try { var connection = await Connection.Create(options.BrowserWSEndpoint, options, _loggerFactory).ConfigureAwait(false); var response = await connection.SendAsync <GetBrowserContextsResponse>("Target.getBrowserContexts"); return(await Browser .CreateAsync(connection, response.BrowserContextIds, options.IgnoreHTTPSErrors, options.DefaultViewport, null) .ConfigureAwait(false)); } catch (Exception ex) { throw new ChromiumProcessException("Failed to create connection", ex); } }
/// <summary> /// Attaches Puppeteer to an existing Chromium instance. The browser will be closed when the Browser is disposed. /// </summary> /// <param name="options">Options for connecting.</param> /// <returns>A connected browser.</returns> public async Task <Browser> ConnectAsync(ConnectOptions options) { try { var connectionDelay = options.SlowMo; var keepAliveInterval = options.KeepAliveInterval; _connection = await Connection.Create(options.BrowserWSEndpoint, connectionDelay, keepAliveInterval); return(await Browser.CreateAsync(_connection, options, null, () => { var closeTask = _connection.SendAsync("Browser.close", null); return null; })); } catch (Exception ex) { throw new Exception("Failed to create connection", ex); } }
/// <summary> /// The method launches a browser instance with given arguments. The browser will be closed when the Browser is disposed. /// </summary> /// <param name="options">Options for launching the browser</param> /// <param name="product">The browser to launch (Chrome, Firefox)</param> /// <returns>A connected browser.</returns> /// <remarks> /// See <a href="https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/">this article</a> /// for a description of the differences between Chromium and Chrome. /// <a href="https://chromium.googlesource.com/chromium/src/+/lkcr/docs/chromium_browser_vs_google_chrome.md">This article</a> describes some differences for Linux users. /// </remarks> public async Task <Browser> LaunchAsync(LaunchOptions options) { EnsureSingleLaunchOrConnect(); string executable = GetOrFetchBrowserExecutable(options); Process = new ChromiumLauncher(executable, options); try { await Process.StartAsync().ConfigureAwait(false); try { var connection = await Connection .Create(Process.EndPoint, options) .ConfigureAwait(false); var browser = await Browser .CreateAsync(connection, Array.Empty <string>(), options.IgnoreHTTPSErrors, options.DefaultViewport, Process) .ConfigureAwait(false); await browser.WaitForTargetAsync(t => t.Type == TargetType.Page).ConfigureAwait(false); return(browser); } catch (Exception ex) { throw new ProcessException("Failed to create connection", ex); } } catch { await Process.KillAsync().ConfigureAwait(false); throw; } }
/// <summary> /// The method launches a browser instance with given arguments. The browser will be closed when the Browser is disposed. /// </summary> /// <param name="options">Options for launching Chrome</param> /// <returns>A connected browser.</returns> /// <remarks> /// See <a href="https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/">this article</a> /// for a description of the differences between Chromium and Chrome. /// <a href="https://chromium.googlesource.com/chromium/src/+/lkcr/docs/chromium_browser_vs_google_chrome.md">This article</a> describes some differences for Linux users. /// </remarks> public async Task <Browser> LaunchAsync(LaunchOptions options) { EnsureSingleLaunchOrConnect(); var chromiumExecutable = GetOrFetchChromeExecutable(options); Process = new ChromiumProcess(chromiumExecutable, options, _loggerFactory); try { await Process.StartAsync().ConfigureAwait(false); try { var connection = await Connection .Create(Process.EndPoint, options, _loggerFactory) .ConfigureAwait(false); var browser = await Browser .CreateAsync(connection, Array.Empty <string>(), options.IgnoreHTTPSErrors, options.DefaultViewport, Process) .ConfigureAwait(false); await EnsureInitialPageAsync(browser).ConfigureAwait(false); return(browser); } catch (Exception ex) { throw new ChromiumProcessException("Failed to create connection", ex); } } catch { await Process.KillAsync().ConfigureAwait(false); throw; } }
/// <summary> /// The method launches a browser instance with given arguments. The browser will be closed when the Browser is disposed. /// </summary> /// <param name="options">Options for launching Chrome</param> /// <param name="chromiumRevision">The revision of Chrome to launch.</param> /// <returns>A connected browser.</returns> /// <remarks> /// See <a href="https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/">this article</a> /// for a description of the differences between Chromium and Chrome. /// <a href="https://chromium.googlesource.com/chromium/src/+/lkcr/docs/chromium_browser_vs_google_chrome.md">This article</a> describes some differences for Linux users. /// </remarks> public async Task <Browser> LaunchAsync(LaunchOptions options, int chromiumRevision) { var chromeArguments = new List <string>(DefaultArgs); _options = options; if (options.AppMode) { options.Headless = false; } else { chromeArguments.AddRange(AutomationArgs); } var userDataDirOption = options.Args.FirstOrDefault(i => i.StartsWith(UserDataDirArgument, StringComparison.Ordinal)); if (string.IsNullOrEmpty(userDataDirOption)) { if (string.IsNullOrEmpty(options.UserDataDir)) { _temporaryUserDataDir = GetTemporaryDirectory(); chromeArguments.Add($"{UserDataDirArgument}={_temporaryUserDataDir}"); } else { chromeArguments.Add($"{UserDataDirArgument}={options.UserDataDir}"); } } else { _options.UserDataDir = userDataDirOption.Replace($"{UserDataDirArgument}=", string.Empty); } if (options.Devtools) { chromeArguments.Add("--auto-open-devtools-for-tabs"); options.Headless = false; } if (options.Headless) { chromeArguments.AddRange(new[] { "--headless", "--disable-gpu", "--hide-scrollbars", "--mute-audio" }); } var chromeExecutable = options.ExecutablePath; if (string.IsNullOrEmpty(chromeExecutable)) { var downloader = Downloader.CreateDefault(); var revisionInfo = downloader.RevisionInfo(Downloader.CurrentPlatform, chromiumRevision); chromeExecutable = revisionInfo.ExecutablePath; } if (!File.Exists(chromeExecutable)) { throw new FileNotFoundException("Failed to launch chrome! path to executable does not exist", chromeExecutable); } if (options.Args.Any()) { chromeArguments.AddRange(options.Args); } _chromeProcess = new Process(); _chromeProcess.EnableRaisingEvents = true; _chromeProcess.StartInfo.UseShellExecute = false; _chromeProcess.StartInfo.FileName = chromeExecutable; _chromeProcess.StartInfo.Arguments = string.Join(" ", chromeArguments); SetEnvVariables(_chromeProcess.StartInfo.Environment, options.Env, Environment.GetEnvironmentVariables()); if (!options.DumpIO) { _chromeProcess.StartInfo.RedirectStandardOutput = false; _chromeProcess.StartInfo.RedirectStandardError = false; } _chromeProcess.Exited += async(sender, e) => { await AfterProcessExit(); }; try { var connectionDelay = options.SlowMo; var browserWSEndpoint = await WaitForEndpoint(_chromeProcess, options.Timeout, options.DumpIO); var keepAliveInterval = options.KeepAliveInterval; _connection = await Connection.Create(browserWSEndpoint, connectionDelay, keepAliveInterval); _processLoaded = true; if (options.LogProcess) { Console.WriteLine($"PROCESS COUNT: {Interlocked.Increment(ref _processCount)}"); } return(await Browser.CreateAsync(_connection, options, _chromeProcess, KillChrome)); } catch (Exception ex) { ForceKillChrome(); throw new ChromeProcessException("Failed to create connection", ex); } }
internal static async Task <Browser> LaunchAsync(Dictionary <string, object> options, int chromiumRevision) { var chromeArguments = new List <string>(_defaultArgs); if (options.ContainsKey("appMode")) { options["headless"] = false; } else { chromeArguments.AddRange(_automationArgs); } if (options.ContainsKey("args") && ((string[])options["args"]).Any(i => i.StartsWith("--user-data-dir", StringComparison.Ordinal))) { if (!options.ContainsKey("userDataDir")) { _temporaryUserDataDir = GetTemporaryDirectory(); chromeArguments.Add($"--user-data-dir=${_temporaryUserDataDir}"); } else { chromeArguments.Add($"--user-data-dir=${options["userDataDir"]}"); } } if (options.TryGetValue("devtools", out var hasDevTools) && (bool)hasDevTools) { chromeArguments.Add("--auto-open-devtools-for-tabs"); options["headless"] = false; } if (options.TryGetValue("headless", out var isHeadless) && (bool)isHeadless) { chromeArguments.AddRange(new[] { "--headless", "--disable-gpu", "--hide-scrollbars", "--mute-audio" }); } var chromeExecutable = (options.GetValueOrDefault("executablePath") ?? "").ToString(); if (string.IsNullOrEmpty(chromeExecutable)) { var downloader = Downloader.CreateDefault(); var revisionInfo = downloader.RevisionInfo(Downloader.CurrentPlatform, chromiumRevision); chromeExecutable = revisionInfo.ExecutablePath; } if (options.ContainsKey("args")) { chromeArguments.AddRange((string[])options["args"]); } _chromeProcess = new Process(); _chromeProcess.StartInfo.FileName = chromeExecutable; _chromeProcess.StartInfo.Arguments = string.Join(" ", chromeArguments); SetEnvVariables(_chromeProcess.StartInfo.Environment, options.ContainsKey("env") ? (IDictionary <string, string>)options["env"] : null, (IDictionary)Environment.GetEnvironmentVariables()); if (!options.ContainsKey("dumpio")) { _chromeProcess.StartInfo.RedirectStandardOutput = false; _chromeProcess.StartInfo.RedirectStandardError = false; } _chromeProcess.Exited += async(sender, e) => { _chromeClosed = true; await KillChrome(); }; try { var connectionDelay = (int)(options.GetValueOrDefault("slowMo") ?? 0); var browserWSEndpoint = await WaitForEndpoint(_chromeProcess, (int)(options.GetValueOrDefault("timeout") ?? 30 * 100), options.ContainsKey("dumpio")); _connection = await Connection.Create(browserWSEndpoint, connectionDelay); return(await Browser.CreateAsync(_connection, options, KillChrome)); } catch (Exception ex) { await ForceKillChrome(); throw new Exception("Failed to create connection", ex); } }