Skip to content

Commit

Permalink
fix(driver): improve Firefox binary location detection. fixes #4
Browse files Browse the repository at this point in the history
  • Loading branch information
bytexenon committed Nov 20, 2024
1 parent 3dec142 commit d8a8afd
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 18 deletions.
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
selenium
selenium
psutil
51 changes: 34 additions & 17 deletions undetected_geckodriver/driver.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Imports #
import os
import shutil
import time

import psutil
from selenium.webdriver.common.driver_finder import DriverFinder
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.firefox.remote_connection import FirefoxRemoteConnection
Expand Down Expand Up @@ -36,7 +38,7 @@ def __init__(

self.service: Service = service or Service()
self.options: Options = options or Options()
self.options.binary_location = self._get_binary_location()
self.options.binary_location = self._find_platform_dependent_executable()
self.keep_alive: bool = keep_alive

self._initialize_service()
Expand All @@ -46,13 +48,6 @@ def _setup_firefox_environment(self) -> None:
self._create_undetected_firefox_directory()
self._patch_libxul_file()

def _get_binary_location(self) -> str:
"""Get the binary location for the undetected Firefox."""
executable_path: str = self._find_platform_dependent_executable(
self._platform_dependent_params["firefox_execs"]
)
return executable_path

def _initialize_service(self) -> None:
"""Initialize the Firefox service and remote connection."""
finder = DriverFinder(self.service, self.options)
Expand All @@ -73,11 +68,34 @@ def _initialize_service(self) -> None:
self._is_remote = False

def _get_firefox_installation_path(self) -> str:
"""Get the installation path of Firefox."""
firefox_paths: list = self._platform_dependent_params["firefox_paths"]
for path in firefox_paths:
if os.path.exists(path):
return path
"""
Unlike _get_binary_location, this method returns the path to the
directory containing the Firefox binary and its libraries.
Normally, it's located in `/usr/lib/firefox`.
"""

# firefox_paths: list = self._platform_dependent_params["firefox_paths"]
# for path in firefox_paths:
# if os.path.exists(path):
# return path

# Fixes #4
# If the first method fails, we can try to find the path by running
# Firefox, checking its process path, and then killing it using psutil.
# This is a last resort method, and might slow down the initialization.
for firefox_exec in self._platform_dependent_params["firefox_execs"]:
if shutil.which(firefox_exec):
process = psutil.Popen(
[firefox_exec, "--headless", "--new-instance"],
stdout=psutil.subprocess.DEVNULL,
stderr=psutil.subprocess.DEVNULL,
)
time.sleep(0.1) # Wait for the process to truly start
process_dir = os.path.dirname(process.exe())
# Kill the process
process.kill()
return process_dir

raise FileNotFoundError("Could not find Firefox installation path")

def _get_undetected_firefox_path(self) -> str:
Expand All @@ -99,7 +117,6 @@ def _patch_libxul_file(self) -> None:
if not os.path.exists(libxul_path):
raise FileNotFoundError(f"Could not find {xul}")

libxul_data = open(libxul_path, "rb").read()
with open(libxul_path, "rb") as file:
libxul_data = file.read()

Expand All @@ -109,9 +126,9 @@ def _patch_libxul_file(self) -> None:
with open(libxul_path, "wb") as file:
file.write(libxul_data)

def _find_platform_dependent_executable(self, executables: list[str]) -> str:
"""Find the platform-dependent executable in the given path."""
for executable in executables:
def _find_platform_dependent_executable(self) -> str:
"""Find the platform-dependent executable for patched Firefox."""
for executable in self._platform_dependent_params["firefox_execs"]:
full_path: str = os.path.join(self._undetected_path, executable)
if os.path.exists(full_path):
return full_path
Expand Down

0 comments on commit d8a8afd

Please sign in to comment.