blob: bcbe11ab46bd25341450e68a0c81911a1f0f1a0b [file] [log] [blame]
// <copyright file="DriverFinder.cs" company="Selenium Committers">
// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The SFC licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
// </copyright>
using OpenQA.Selenium.Manager;
namespace OpenQA.Selenium;
/// <summary>
/// Discovers and manages paths to browser drivers and browser binaries.
/// Uses Selenium Manager to automatically locate compatible driver and browser versions.
/// </summary>
/// <param name="options">The driver options specifying browser configuration.</param>
/// <exception cref="ArgumentNullException">When <paramref name="options"/> is null.</exception>
/// <remarks>
/// <b>Warning: This is an experimental API that is subject to change in future versions.</b>
/// </remarks>
public class DriverFinder(DriverOptions options)
{
private string _driverPath = null!;
private string _browserPath = null!;
private readonly DriverOptions options = options ?? throw new ArgumentNullException(nameof(options));
/// <summary>
/// Gets the path to the browser driver executable.
/// Discovers the driver path on first call using Selenium Manager.
/// </summary>
/// <param name="cancellationToken">A cancellation token to observe while waiting for the task to complete.</param>
/// <returns>A task that represents the asynchronous operation. The task result contains the full path to the driver executable.</returns>
/// <exception cref="NoSuchDriverException">When browser name is not specified or driver/browser cannot be found.</exception>
public async ValueTask<string> GetDriverPathAsync(CancellationToken cancellationToken = default)
{
if (_driverPath is null)
{
await DiscoverBinaryPathsAsync(cancellationToken).ConfigureAwait(false);
}
return _driverPath!;
}
/// <summary>
/// Gets the path to the browser binary.
/// Discovers the browser path on first call using Selenium Manager.
/// </summary>
/// <param name="cancellationToken">A cancellation token to observe while waiting for the task to complete.</param>
/// <returns>A task that represents the asynchronous operation. The task result contains the full path to the browser binary.</returns>
/// <exception cref="NoSuchDriverException">When browser name is not specified or driver/browser cannot be found.</exception>
public async ValueTask<string> GetBrowserPathAsync(CancellationToken cancellationToken = default)
{
if (_browserPath is null)
{
await DiscoverBinaryPathsAsync(cancellationToken).ConfigureAwait(false);
}
return _browserPath!;
}
private async ValueTask DiscoverBinaryPathsAsync(CancellationToken cancellationToken = default)
{
if (string.IsNullOrWhiteSpace(options.BrowserName))
{
throw new NoSuchDriverException("Browser name must be specified to find the driver.");
}
BrowserDiscoveryResult smResult = await SeleniumManager.DiscoverBrowserAsync(options.BrowserName!, new BrowserDiscoveryOptions
{
BrowserVersion = options.BrowserVersion,
BrowserPath = options.BinaryLocation,
Proxy = options.Proxy?.SslProxy ?? options.Proxy?.HttpProxy
}, cancellationToken).ConfigureAwait(false);
string driverPath = smResult.DriverPath;
string browserPath = smResult.BrowserPath;
if (!File.Exists(driverPath))
{
throw new NoSuchDriverException($"Driver not found: {driverPath}");
}
if (!File.Exists(browserPath))
{
throw new NoSuchDriverException($"Browser not found: {browserPath}");
}
_driverPath = driverPath;
_browserPath = browserPath;
}
}