code: // 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.
  
  package org.openqa.selenium.testing;
  
  import java.io.File;
  import java.io.IOException;
  import java.io.UncheckedIOException;
  import java.nio.charset.StandardCharsets;
  import java.nio.file.Files;
  import java.util.Map;
  import java.util.regex.Matcher;
  import java.util.regex.Pattern;
  import org.openqa.selenium.Capabilities;
  import org.openqa.selenium.HasCapabilities;
  import org.openqa.selenium.JavascriptExecutor;
  import org.openqa.selenium.Platform;
  import org.openqa.selenium.WebDriver;
  import org.openqa.selenium.htmlunit.HtmlUnitDriver;
  
  public class TestUtilities {
  
    public static String getUserAgent(WebDriver driver) {
      try {
        return (String) ((JavascriptExecutor) driver).executeScript("return navigator.userAgent;");
      } catch (Throwable e) {
        // Some drivers will only execute JS once a page has been loaded. Since those
        // drivers aren't Firefox or IE, we don't worry about that here.
        //
        // Non-javascript-enabled HtmlUnit throws an UnsupportedOperationException here.
        // Let's just ignore that.
        return "";
      }
    }
  
    public static boolean isFirefox(WebDriver driver) {
      return getUserAgent(driver).contains("Firefox");
    }
  
    public static boolean isFirefoxVersionOlderThan(int version, WebDriver driver) {
      return isFirefox(driver) && getFirefoxVersion(driver) < version;
    }
  
    public static boolean isInternetExplorer(WebDriver driver) {
      String userAgent = getUserAgent(driver);
      return userAgent != null && (userAgent.contains("MSIE") || userAgent.contains("Trident"));
    }
  
    public static boolean isChrome(WebDriver driver) {
      return !(driver instanceof HtmlUnitDriver) && getUserAgent(driver).contains("Chrome");
    }
  
    public static int getChromeVersion(WebDriver driver) {
      if (!(driver instanceof HasCapabilities)) {
        // Driver does not support capabilities -- not a chromedriver at all.
        return 0;
      }
      Capabilities caps = ((HasCapabilities) driver).getCapabilities();
      String chromedriverVersion = (String) caps.getCapability("chrome.chromedriverVersion");
      if (chromedriverVersion == null) {
        Object chrome = caps.getCapability("chrome");
        if (chrome != null) {
          chromedriverVersion = (String) ((Map<?, ?>) chrome).get("chromedriverVersion");
        }
      }
      if (chromedriverVersion != null) {
        String[] versionMajorMinor = chromedriverVersion.split("\\.", 2);
        if (versionMajorMinor.length > 1) {
          try {
            return Integer.parseInt(versionMajorMinor[0]);
          } catch (NumberFormatException e) {
            // First component of the version is not a number -- not a chromedriver.
            return 0;
          }
        }
      }
      return 0;
    }
  
    /**
     * Finds the Firefox version of the given webdriver and returns it as an integer. For instance,
     * '14.0.1' will translate to 14.
     *
     * @param driver The driver to find the version for.
     * @return The found version, or 0 if no version could be found.
     */
    public static int getFirefoxVersion(WebDriver driver) {
      // extract browser string
      Pattern browserPattern = Pattern.compile("Firefox/\\d+.");
      Matcher browserMatcher = browserPattern.matcher(getUserAgent(driver));
      if (!browserMatcher.find()) {
        return 0;
      }
      String browserStr = browserMatcher.group();
  
      // extract version string
      Pattern versionPattern = Pattern.compile("\\d+");
      Matcher versionMatcher = versionPattern.matcher(browserStr);
      if (!versionMatcher.find()) {
        return 0;
      }
      return Integer.parseInt(versionMatcher.group());
    }
  
    /**
     * Finds the IE major version of the given webdriver and returns it as an integer. For instance,
     * '10.6' will translate to 10.
     *
     * @param driver The driver to find the version for.
     * @return The found version, or 0 if no version could be found.
     */
    public static int getIEVersion(WebDriver driver) {
      String userAgent = getUserAgent(driver);
      // extract browser string
      Pattern browserPattern = Pattern.compile("MSIE\\s+\\d+\\.");
      Matcher browserMatcher = browserPattern.matcher(userAgent);
      // IE dropped the "MSIE" token from its user agent string starting with IE11.
      Pattern tridentPattern = Pattern.compile("Trident/\\d+\\.");
      Matcher tridentMatcher = tridentPattern.matcher(userAgent);
  
      Matcher versionMatcher;
      if (browserMatcher.find()) {
        versionMatcher = Pattern.compile("(\\d+)").matcher(browserMatcher.group());
      } else if (tridentMatcher.find()) {
        versionMatcher = Pattern.compile("rv:(\\d+)").matcher(userAgent);
      } else {
        return Integer.MAX_VALUE; // Because people check to see if we're at this version or less
      }
  
      // extract version string
      if (!versionMatcher.find()) {
        return 0;
      }
      return Integer.parseInt(versionMatcher.group(1));
    }
  
    public static Platform getEffectivePlatform() {
      return Platform.getCurrent();
    }
  
    /** Returns Platform where the browser (driven by given WebDriver) runs on. */
    public static Platform getEffectivePlatform(WebDriver driver) {
      if (!(driver instanceof HasCapabilities)) {
        throw new RuntimeException("WebDriver must implement HasCapabilities");
      }
  
      Capabilities caps = ((HasCapabilities) driver).getCapabilities();
      return caps.getPlatformName();
    }
  
    public static boolean isLocal() {
      return !(Boolean.getBoolean("selenium.browser.remote")
          || Boolean.getBoolean("selenium.browser.grid"));
    }
  
    public static boolean isOnTravis() {
      return Boolean.parseBoolean(System.getenv("TRAVIS"));
    }
  
    public static boolean isOnGitHubActions() {
      return Boolean.parseBoolean(System.getenv("GITHUB_ACTIONS"));
    }
  
    public static File createTmpFile(String content) {
      try {
        File f = File.createTempFile("webdriver", "tmp");
        f.deleteOnExit();
        Files.write(f.toPath(), content.getBytes(StandardCharsets.UTF_8));
        return f;
      } catch (IOException e) {
        throw new UncheckedIOException(e);
      }
    }
  }
  