All Downloads are FREE. Search and download functionalities are using the official Maven repository.

me.saro.selenium.ChromeDriverBuilder.kt Maven / Gradle / Ivy

There is a newer version: 4.26.0.0
Show newest version
package me.saro.selenium


import me.saro.selenium.comm.Utils
import me.saro.selenium.model.DownloadStrategy
import me.saro.selenium.model.PathManager
import me.saro.selenium.model.SeleniumChromeException
import me.saro.selenium.service.ChromeDriverPlus
import me.saro.selenium.service.ChromeManager
import org.openqa.selenium.Dimension
import org.openqa.selenium.chrome.ChromeDriver
import org.openqa.selenium.chrome.ChromeOptions
import java.io.File
import java.time.Duration

class ChromeDriverBuilder(
    private val manageChromePath: File,
) {
    companion object {
        private var created = false
    }

    private var downloadStrategy: DownloadStrategy = DownloadStrategy.DOWNLOAD_IF_NO_VERSION
    private val options: MutableSet = mutableSetOf()
    private val properties: MutableMap = mutableMapOf()
    private val log = Utils.getLogger(ChromeDriverBuilder::class)

    fun downloadStrategy(downloadStrategy: DownloadStrategy): ChromeDriverBuilder {
        this.downloadStrategy = downloadStrategy
        return this
    }

    fun option(option: String): ChromeDriverBuilder {
        assert (option.isNotBlank()) { "option is blank" }
        val lof = option.lastIndexOf('=')
        if (lof != -1) {
            val key = option.substring(0, lof)
            options.removeIf { it.startsWith(key) }
        }
        when (option) {
            "--headless" -> throw SeleniumChromeException("The --headless option cannot be used here.\nYou can use the methods openBackground(), openWith(), or newChromeDriver() through ChromeDriverManager.")
        }
        options.add(option)
        return this
    }

    fun enableRecommendChromeOptions(disabledSecurity: Boolean): ChromeDriverBuilder {
        option("--user-data-dir=" + System.getProperty("java.io.tmpdir")) // Prevents socket errors.
            .option("--disable-infobars") // Disables browser information bar.
            .option("--disable-dev-shm-usage") // Ignores the limit on temporary disk space for the browser.
            .option("--blink-settings=imagesEnabled=false") // Disables image loading.
            .option("--disable-extensions")
            .option("--disable-popup-blocking")
            .option("--disable-gpu")
        if (disabledSecurity) {
            properties["webdriver.chrome.whitelistedIps"] = ""
            option("--no-sandbox")
                .option("--ignore-certificate-errors")
        }
        return this
    }

    @Synchronized
    fun build(): ChromeDriverManager {
        if (created) {
            log.warning("SeleniumAllInOne is already created.\nIt is a singleton object.")
        }
        val pathManager = PathManager.create(manageChromePath)
        ChromeManager.load(pathManager, downloadStrategy)
        properties.forEach(System::setProperty)
        System.setProperty("webdriver.chrome.driver", pathManager.chromedriverBinPath)
        created = true
        return ChromeDriverManagerImpl(pathManager.chromeBinPath, options.toSet())
    }

    class ChromeDriverManagerImpl(
        private val chromeBinPath: String,
        private val options: Set
    ): ChromeDriverManager {
        private val log = Utils.getLogger(ChromeDriverManagerImpl::class)

        override fun  openWith(url: String, addOption: Set, use: ChromeDriverPlus.() -> T): T {
            val driver = newChromeDriver(createChromeOptions(addOption))
            try {
                return use(ChromeDriverPlus(driver).apply {
                    windowSize(2000, 3000)
                    val duration =  Duration.ofSeconds(20)
                    implicitWaitTimeout = duration
                    pageLoadTimeout = duration
                    move(url)
                })
            } finally {
                try { driver.close() } catch (e: Exception) {}
                try { driver.quit() } catch (e: Exception) {}
                log.info("chrome driver closed.")
            }
        }

        override fun newChromeDriver(chromeOptions: ChromeOptions): ChromeDriver =
            ChromeDriver(chromeOptions.setBinary(chromeBinPath))

        private fun createChromeOptions(addOption: Set): ChromeOptions =
            ChromeOptions().apply {
                options.forEach(::addArguments)
                addOption.forEach(::addArguments)
            }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy