Skip to content

Commit

Permalink
Create a new browser package for brand support:
Browse files Browse the repository at this point in the history
sys utils needs to be refactored before we can finish browser
since sys utils will provide mechanisms to find chromium
issue where BROWSER_PATH might now also be firefox
but I suppose that just means you would have to specify firefox
I think brave will work with this
  • Loading branch information
ayjayt committed Jan 5, 2025
1 parent 46c58d6 commit 15f920f
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 117 deletions.
Empty file.
49 changes: 49 additions & 0 deletions choreographer/_browser/_unix_pipe_chromium_wrapper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
"""
_unix_pipe_chromium_wrapper.py provides proper fds to chrome.
By running chromium in a new process (this wrapper), we guarantee
the user hasn't stolen one of our desired file descriptors, which
the OS gives away first-come-first-serve everytime someone opens a
file. chromium demands we use 3 and 4.
"""

import os

# importing modules has side effects, so we do this before imports
# ruff: noqa: E402

# chromium reads on 3, writes on 4
os.dup2(0, 3) # make our stdin their input
os.dup2(1, 4) # make our stdout their output

_inheritable = True
os.set_inheritable(4, _inheritable)
os.set_inheritable(3, _inheritable)

import signal
import subprocess
import sys
from functools import partial

# we're a wrapper, the cli is everything that came after us
cli = sys.argv[1:]
process = subprocess.Popen(cli, pass_fds=(3, 4)) # noqa: S603 untrusted input


def kill_proc(process, _sig_num, _frame):
process.terminate()
process.wait(5) # 5 seconds to clean up nicely, it's a lot
process.kill()


kp = partial(kill_proc, process)
signal.signal(signal.SIGTERM, kp)
signal.signal(signal.SIGINT, kp)

process.wait()

# not great but it seems that
# pipe isn't always closed when chrome closes
# so we pretend to be chrome and send a bye instead
# also, above depends on async/sync, platform, etc
print("{bye}")
75 changes: 75 additions & 0 deletions choreographer/_browser/chromium.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
"""chromium.py provides a class proving tools for running chromium browsers."""

import os
import platform
import sys
from pathlib import Path

# TODO(Andrew): move this to its own subpackage comm # noqa: FIX002, TD003
from choreographer._pipe import Pipe, WebSocket

if platform.system() == "Windows":
import msvcrt


class Chromium:
def __init__(self, pipe):
self._comm = pipe
# extra information from pipe

# where do we get user data dir
def get_cli(self, temp_dir, **kwargs):
gpu_enabled = kwargs.pop("with_gpu", False)
headless = kwargs.pop("headless", True)
sandbox = kwargs.pop("with_sandbox", False)
if kwargs:
raise RuntimeError(
"Chromium.get_cli() received " f"invalid args: {kwargs.keys()}",
)
path = None # TODO(Andrew): not legit # noqa: FIX002,TD003
chromium_wrapper_path = Path(__file__).resolve().parent / "chromium_wrapper.py"
if platform.system() != "Windows":
cli = [
sys.executable,
chromium_wrapper_path,
path,
]
else:
cli = [
path,
]

cli.extend(
[
"--disable-breakpad",
"--allow-file-access-from-files",
"--enable-logging=stderr",
f"--user-data-dir={temp_dir}",
"--no-first-run",
"--enable-unsafe-swiftshader",
],
)
if not gpu_enabled:
cli.append("--disable-gpu")
if headless:
cli.append("--headless")
if not sandbox:
cli.append("--no-sandbox")

if isinstance(self._comm, Pipe):
cli.append("--remote-debugging-pipe")
if platform.system() == "Windows":
_inheritable = True
write_handle = msvcrt.get_osfhandle(self._comm.from_choreo_to_external)
read_handle = msvcrt.get_osfhandle(self._comm.from_external_to_choreo)
os.set_handle_inheritable(write_handle, _inheritable)
os.set_handle_inheritable(read_handle, _inheritable)
cli += [
f"--remote-debugging-io-pipes={read_handle!s},{write_handle!s}",
]
elif isinstance(self._comm, WebSocket):
raise NotImplementedError("Websocket style comms are not implemented yet")


def get_env():
return os.environ().copy()
117 changes: 0 additions & 117 deletions choreographer/_system_utils/_chrome_wrapper.py

This file was deleted.

0 comments on commit 15f920f

Please sign in to comment.