Skip to content

Commit 15f920f

Browse files
committed
Create a new browser package for brand support:
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
1 parent 46c58d6 commit 15f920f

File tree

4 files changed

+124
-117
lines changed

4 files changed

+124
-117
lines changed

choreographer/_browser/__init__.py

Whitespace-only changes.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
"""
2+
_unix_pipe_chromium_wrapper.py provides proper fds to chrome.
3+
4+
By running chromium in a new process (this wrapper), we guarantee
5+
the user hasn't stolen one of our desired file descriptors, which
6+
the OS gives away first-come-first-serve everytime someone opens a
7+
file. chromium demands we use 3 and 4.
8+
"""
9+
10+
import os
11+
12+
# importing modules has side effects, so we do this before imports
13+
# ruff: noqa: E402
14+
15+
# chromium reads on 3, writes on 4
16+
os.dup2(0, 3) # make our stdin their input
17+
os.dup2(1, 4) # make our stdout their output
18+
19+
_inheritable = True
20+
os.set_inheritable(4, _inheritable)
21+
os.set_inheritable(3, _inheritable)
22+
23+
import signal
24+
import subprocess
25+
import sys
26+
from functools import partial
27+
28+
# we're a wrapper, the cli is everything that came after us
29+
cli = sys.argv[1:]
30+
process = subprocess.Popen(cli, pass_fds=(3, 4)) # noqa: S603 untrusted input
31+
32+
33+
def kill_proc(process, _sig_num, _frame):
34+
process.terminate()
35+
process.wait(5) # 5 seconds to clean up nicely, it's a lot
36+
process.kill()
37+
38+
39+
kp = partial(kill_proc, process)
40+
signal.signal(signal.SIGTERM, kp)
41+
signal.signal(signal.SIGINT, kp)
42+
43+
process.wait()
44+
45+
# not great but it seems that
46+
# pipe isn't always closed when chrome closes
47+
# so we pretend to be chrome and send a bye instead
48+
# also, above depends on async/sync, platform, etc
49+
print("{bye}")

choreographer/_browser/chromium.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
"""chromium.py provides a class proving tools for running chromium browsers."""
2+
3+
import os
4+
import platform
5+
import sys
6+
from pathlib import Path
7+
8+
# TODO(Andrew): move this to its own subpackage comm # noqa: FIX002, TD003
9+
from choreographer._pipe import Pipe, WebSocket
10+
11+
if platform.system() == "Windows":
12+
import msvcrt
13+
14+
15+
class Chromium:
16+
def __init__(self, pipe):
17+
self._comm = pipe
18+
# extra information from pipe
19+
20+
# where do we get user data dir
21+
def get_cli(self, temp_dir, **kwargs):
22+
gpu_enabled = kwargs.pop("with_gpu", False)
23+
headless = kwargs.pop("headless", True)
24+
sandbox = kwargs.pop("with_sandbox", False)
25+
if kwargs:
26+
raise RuntimeError(
27+
"Chromium.get_cli() received " f"invalid args: {kwargs.keys()}",
28+
)
29+
path = None # TODO(Andrew): not legit # noqa: FIX002,TD003
30+
chromium_wrapper_path = Path(__file__).resolve().parent / "chromium_wrapper.py"
31+
if platform.system() != "Windows":
32+
cli = [
33+
sys.executable,
34+
chromium_wrapper_path,
35+
path,
36+
]
37+
else:
38+
cli = [
39+
path,
40+
]
41+
42+
cli.extend(
43+
[
44+
"--disable-breakpad",
45+
"--allow-file-access-from-files",
46+
"--enable-logging=stderr",
47+
f"--user-data-dir={temp_dir}",
48+
"--no-first-run",
49+
"--enable-unsafe-swiftshader",
50+
],
51+
)
52+
if not gpu_enabled:
53+
cli.append("--disable-gpu")
54+
if headless:
55+
cli.append("--headless")
56+
if not sandbox:
57+
cli.append("--no-sandbox")
58+
59+
if isinstance(self._comm, Pipe):
60+
cli.append("--remote-debugging-pipe")
61+
if platform.system() == "Windows":
62+
_inheritable = True
63+
write_handle = msvcrt.get_osfhandle(self._comm.from_choreo_to_external)
64+
read_handle = msvcrt.get_osfhandle(self._comm.from_external_to_choreo)
65+
os.set_handle_inheritable(write_handle, _inheritable)
66+
os.set_handle_inheritable(read_handle, _inheritable)
67+
cli += [
68+
f"--remote-debugging-io-pipes={read_handle!s},{write_handle!s}",
69+
]
70+
elif isinstance(self._comm, WebSocket):
71+
raise NotImplementedError("Websocket style comms are not implemented yet")
72+
73+
74+
def get_env():
75+
return os.environ().copy()

choreographer/_system_utils/_chrome_wrapper.py

Lines changed: 0 additions & 117 deletions
This file was deleted.

0 commit comments

Comments
 (0)