Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions openwpm/browser_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,25 @@ def check_queue(launch_status: Dict[str, bool]) -> Any:
# Resets the command/status queues
(self.command_queue, self.status_queue) = (Queue(), Queue())

# Create a unique temporary directory for this spawn attempt.
# This is created inside the loop so each retry gets a fresh
# tmpdir (close_browser_manager deletes it on failure).
if self.browser_params.tmpdir is not None:
self.logger.debug(
"BROWSER %i: Deleting leftover temp directory %s"
% (self.browser_id, self.browser_params.tmpdir)
)
shutil.rmtree(self.browser_params.tmpdir, ignore_errors=True)
self.browser_params.tmpdir = Path(
tempfile.mkdtemp(
prefix="openwpm_", dir=os.getenv("TMPDIR", default="/tmp")
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

os.getenv does not accept default as a keyword argument (its parameters are positional-only in supported Python versions). This will raise a TypeError at runtime. Use os.getenv(\"TMPDIR\", \"/tmp\") (positional default) or, for better portability, consider using tempfile.gettempdir()/Path(tempfile.gettempdir()) instead of hard-coding /tmp.

Suggested change
prefix="openwpm_", dir=os.getenv("TMPDIR", default="/tmp")
prefix="openwpm_", dir=tempfile.gettempdir()

Copilot uses AI. Check for mistakes.
)
)
self.logger.debug(
"BROWSER %i: Using temp dir %s"
% (self.browser_id, self.browser_params.tmpdir)
)

# builds and launches the browser_manager

self.browser_manager = BrowserManager(
Expand Down Expand Up @@ -341,6 +360,22 @@ def close_browser_manager(self, force: bool = False) -> None:
if not shutdown_complete:
self.kill_browser_manager()

# Delete the temporary directory used by geckodriver.
if self.browser_params.tmpdir is not None:
try:
shutil.rmtree(self.browser_params.tmpdir)
self.logger.debug(
"BROWSER %i: Deleted temp dir %s"
% (self.browser_id, self.browser_params.tmpdir)
)
self.browser_params.tmpdir = None
except Exception:
self.logger.warning(
"BROWSER %i: Failed to delete temp dir %s"
% (self.browser_id, self.browser_params.tmpdir),
exc_info=True,
)

def execute_command_sequence(
self,
# Quoting to break cyclic import, see https://stackoverflow.com/a/39757388
Expand Down
13 changes: 13 additions & 0 deletions openwpm/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ class BrowserParams(DataClassJsonMixin):
default=Path(tempfile.gettempdir()),
metadata=DCJConfig(encoder=path_to_str, decoder=str_to_path),
)

"""
The tmp_profile_dir defaults to the OS's temporary file folder (typically /tmp) and is where the generated
browser profiles and residual files are stored.
Expand Down Expand Up @@ -139,6 +140,18 @@ class BrowserParams(DataClassJsonMixin):

"""

tmpdir: Optional[Path] = field(
default=None,
metadata=DCJConfig(encoder=path_to_str, decoder=str_to_path),
)
"""
The temporary directory used by `geckodriver`. This is configured in
`BrowserManager.run` and then deleted when the browser is finished. We do
this because it seems that `geckodriver` doesn't clean up its temporary
files (in particular, a copy of the extension XPI file), so we need to do
so ourselves.
"""

recovery_tar: Optional[Path] = None
donottrack: bool = False
tracking_protection: bool = False
Expand Down
10 changes: 10 additions & 0 deletions openwpm/deploy_browsers/deploy_firefox.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,15 @@ def deploy_firefox(
# Launch the webdriver
status_queue.put(("STATUS", "Launch Attempted", None))

# Use browser_params.tmpdir as the temporary directory. This is so that
# geckodriver makes its copy of the extension XPI file in tmpdir, so
# we can delete it later and not have it left behind. I make a shallow
# copy of `os.environ` because I'm a little nervous about modifying the
# OpenWPM process' environment.
env = os.environ.copy()
if browser_params.tmpdir is not None:
env["TMPDIR"] = str(browser_params.tmpdir)

fo.binary_location = firefox_binary_path
geckodriver_path = subprocess.check_output(
"which geckodriver", encoding="utf-8", shell=True
Expand All @@ -149,6 +158,7 @@ def deploy_firefox(
service=Service(
executable_path=geckodriver_path,
log_output=open(webdriver_interceptor.fifo, "w"),
env=env,
),
)

Expand Down
Loading