Spaces:
Paused
Paused
Update app.py
Browse files
app.py
CHANGED
|
@@ -72,6 +72,94 @@ def _detect_browser() -> str:
|
|
| 72 |
BROWSER = _detect_browser()
|
| 73 |
print(f"๐ Browser: {BROWSER}")
|
| 74 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 75 |
|
| 76 |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 77 |
# โโ Xvfb Management (per-display) โโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
@@ -160,11 +248,12 @@ def _kill_proc(proc: "subprocess.Popen | None"):
|
|
| 160 |
def _kill_display_processes(display: str):
|
| 161 |
"""ููุชู ูู ุงูุนู
ููุงุช ุงูู
ุฑุชุจุทุฉ ุจู display ู
ุนูู."""
|
| 162 |
env_d = {**os.environ, "DISPLAY": display}
|
| 163 |
-
# ูุชู ุงูู
ุชุตูุญ
|
|
|
|
| 164 |
for b in ["firefox", "firefox-esr", "chromium", "chrome"]:
|
| 165 |
try:
|
| 166 |
subprocess.run(
|
| 167 |
-
["pkill", "-f", f"[{b[0]}]{b[1:]}.*{display}"],
|
| 168 |
timeout=3, capture_output=True
|
| 169 |
)
|
| 170 |
except Exception:
|
|
@@ -230,8 +319,16 @@ async def reset_user_computer(user_id: str) -> dict:
|
|
| 230 |
display = sess["display"]
|
| 231 |
print(f"[reset] ๐ Resetting computer for user '{user_id}' on {display}")
|
| 232 |
|
| 233 |
-
# ูุชู ุงูู
ุชุตูุญ
|
| 234 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 235 |
sess["browser_proc"] = None
|
| 236 |
|
| 237 |
# ูุชู Xvfb
|
|
@@ -241,14 +338,22 @@ async def reset_user_computer(user_id: str) -> dict:
|
|
| 241 |
# ุชูุธูู ุดุงู
ู ููุฐุง ุงูู display
|
| 242 |
_kill_display_processes(display)
|
| 243 |
|
| 244 |
-
# ุชูุธูู
|
|
|
|
|
|
|
| 245 |
try:
|
| 246 |
subprocess.run(
|
| 247 |
-
"rm -f ~/.mozilla/firefox/*/lock ~/.mozilla/firefox/*/.parentlock
|
|
|
|
|
|
|
|
|
|
| 248 |
shell=True, timeout=5, capture_output=True
|
| 249 |
)
|
| 250 |
except Exception:
|
| 251 |
pass
|
|
|
|
|
|
|
|
|
|
| 252 |
|
| 253 |
# ุชุดุบูู Xvfb ุฌุฏูุฏ (ุฎุงุฑุฌ ุงูู lock ูุฃู start_xvfb ูุณุชุบุฑู ููุชุงู)
|
| 254 |
new_proc = await asyncio.to_thread(_start_xvfb, display)
|
|
@@ -1009,12 +1114,18 @@ async def handle_action(ws: WebSocket, msg: dict, sess: dict):
|
|
| 1009 |
await send({"type": "ack", "action": "open_app"})
|
| 1010 |
return
|
| 1011 |
if "firefox" in cmd.lower():
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1012 |
await run_cmd(
|
| 1013 |
-
"pkill -f '[f]irefox' 2>/dev/null; sleep 0.
|
| 1014 |
-
"rm -f ~/.mozilla/firefox/*/lock ~/.mozilla/firefox/*/.parentlock 2>/dev/null; "
|
| 1015 |
-
"echo CLEANED",
|
| 1016 |
display, timeout=8
|
| 1017 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1018 |
env = {**os.environ, "DISPLAY": display}
|
| 1019 |
proc = subprocess.Popen(cmd, shell=True, env=env,
|
| 1020 |
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
@@ -1033,16 +1144,19 @@ async def handle_action(ws: WebSocket, msg: dict, sess: dict):
|
|
| 1033 |
# โโ open_browser โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1034 |
elif action == "open_browser":
|
| 1035 |
url = _safe_search(data.get("url", "") or "about:blank")
|
| 1036 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1037 |
await run_cmd(
|
| 1038 |
-
"pkill -f '[f]irefox' 2>/dev/null; sleep 0.
|
| 1039 |
-
"rm -f ~/.mozilla/firefox/*/lock ~/.mozilla/firefox/*/.parentlock 2>/dev/null; "
|
| 1040 |
-
"echo CLEANED",
|
| 1041 |
display, timeout=8
|
| 1042 |
)
|
|
|
|
| 1043 |
env = {**os.environ, "DISPLAY": display}
|
| 1044 |
proc = subprocess.Popen(
|
| 1045 |
-
[BROWSER, "--no-remote", url], env=env,
|
| 1046 |
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
|
| 1047 |
)
|
| 1048 |
with _display_lock:
|
|
|
|
| 72 |
BROWSER = _detect_browser()
|
| 73 |
print(f"๐ Browser: {BROWSER}")
|
| 74 |
|
| 75 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 76 |
+
# โโ Firefox Profile (per-user, isolated, crash-recovery DISABLED) โ
|
| 77 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 78 |
+
# ุงูู
ุดููุฉ ุงูุฌุฐุฑูุฉ ุงูุชู ูุฐุง ุงููุณู
ูุญูููุง:
|
| 79 |
+
# ุนูุฏ ูุชู Firefox (ุญุชู ุจู pkill "ูุทูู")ุ ูุง ููุบูู ุจุดูู ูุธูู ุฏุงุฆู
ุงู ุนูู
|
| 80 |
+
# ุณูุฑูุฑ ุจู
ูุงุฑุฏ ู
ุญุฏูุฏุฉ/Xvfbุ ูุชูุณุฌููู ุงูุฌูุณุฉ ุนูู ุฃููุง "crashed" ุฏุงุฎู
|
| 81 |
+
# sessionstore.jsonlz4 ุงูุฎุงุต ุจุงูุจุฑููุงูู. ูู ุงูู
ุฑุฉ ุงูุชุงููุฉ ููุชุญ Firefox
|
| 82 |
+
# ููุนุฑุถ ุดุงุดุฉ "Sorry. We're having trouble getting your pages back" ุจุฏู
|
| 83 |
+
# ุงูุตูุญุฉ ุงูู
ุทููุจุฉ โ ููุฐู ูู ุงูุดุงุดุฉ ุงูุณูุฏุงุก/ุงููุงุดูุฉ ุงูุชู ุชุตู ูููุทุฉ "ูุงุฌุญุฉ"
|
| 84 |
+
# ุชูููุงู (ููุณุช ุณูุฏุงุก ูุนูุงู) ููููุง ูุง ุชุญุชูู ุนูู ุงูู
ุญุชูู ุงูู
ุทููุจ ุฃุจุฏุงู.
|
| 85 |
+
# ุงูุญู ุงูุฌุฐุฑู: ุจุฑููุงูู ุฎุงุต ุจูู ู
ุณุชุฎุฏู
(isolated) ู
ุน user.js ูุนุทูู ุชู
ุงู
ุงู:
|
| 86 |
+
# - ุงุณุชุฑุฌุงุน ุงูุฌูุณุฉ ุจุนุฏ ุงูุชุญุทูู
(session restore prompt)
|
| 87 |
+
# - ุฃู ู
ุญุงููุฉ ูุฅุนุงุฏุฉ ูุชุญ ุชุจููุจุงุช ุณุงุจูุฉ
|
| 88 |
+
# ุจูุฐุงุ ูู ูุชุญ ููุงูุฑูููุณ ูุจุฏุฃ ุตูุญุฉ ูุธููุฉ ูุงุฑุบุฉ ุฏุงุฆู
ุงูุ ุจุบุถ ุงููุธุฑ ุนู ููููุฉ
|
| 89 |
+
# ุฅุบูุงูู ุณุงุจูุงู.
|
| 90 |
+
|
| 91 |
+
FIREFOX_PROFILE_PREFS = """
|
| 92 |
+
// โโ ุชุนุทูู ุงุณุชุฑุฌุงุน ุงูุฌูุณุฉ ููุงุฆูุงู (ุณุจุจ ุดุงุดุฉ "Restore Session") โโ
|
| 93 |
+
user_pref("browser.sessionstore.resume_from_crash", false);
|
| 94 |
+
user_pref("browser.sessionstore.resume_session_once", false);
|
| 95 |
+
user_pref("browser.sessionstore.max_resumed_crashes", -1);
|
| 96 |
+
user_pref("browser.sessionstore.restore_on_demand", false);
|
| 97 |
+
user_pref("browser.sessionstore.enabled", false);
|
| 98 |
+
user_pref("browser.sessionstore.privacy_level", 2);
|
| 99 |
+
user_pref("browser.startup.page", 0);
|
| 100 |
+
user_pref("browser.startup.homepage_override.mstone", "ignore");
|
| 101 |
+
user_pref("toolkit.startup.max_resumed_crashes", -1);
|
| 102 |
+
// ุชุนุทูู ูุงูุฐุฉ "Restore previous session" ูููุงูุฐ ุงูุฃุฒู
ุงุช ุงูู
ุฎุชููุฉ
|
| 103 |
+
user_pref("browser.sessionstore.max_tabs_undo", 0);
|
| 104 |
+
user_pref("browser.sessionstore.max_windows_undo", 0);
|
| 105 |
+
user_pref("browser.tabs.crashReporting.sendReport", false);
|
| 106 |
+
user_pref("browser.crashReports.unsubmittedCheck.autoSubmit2", false);
|
| 107 |
+
user_pref("browser.crashReports.unsubmittedCheck.enabled", false);
|
| 108 |
+
user_pref("toolkit.crashreporter.infoURL", "");
|
| 109 |
+
// ุชุนุทูู ุดุงุดุฉ "Restore" ููุฐูู ุฃู ุฅุดุนุงุฑ ุชุญุทูู
|
| 110 |
+
user_pref("browser.sessionstore.resumeFromCrash", false);
|
| 111 |
+
user_pref("dom.ipc.plugins.flash.subprocess.crashreporter.enabled", false);
|
| 112 |
+
// ุฅูุบุงุก ุงุณุชุนุงุฏุฉ ุขุฎุฑ ุฌูุณุฉ ุชู
ุงู
ุงู + ุฏุงุฆู
ุงู about:blank
|
| 113 |
+
user_pref("browser.startup.homepage", "about:blank");
|
| 114 |
+
// ุชุนุทูู ุชุญุฏูุซุงุช ูุฑุณุงุฆู onboarding ุงูุชู ูุฏ ุชุจุทุฆ ุฃู ุชุญุฌุจ ุงูููุทุฉ
|
| 115 |
+
user_pref("browser.shell.checkDefaultBrowser", false);
|
| 116 |
+
user_pref("browser.aboutwelcome.enabled", false);
|
| 117 |
+
user_pref("browser.startup.firstrunSkipsHomepage", true);
|
| 118 |
+
user_pref("startup.homepage_welcome_url", "");
|
| 119 |
+
user_pref("startup.homepage_welcome_url.additional", "");
|
| 120 |
+
user_pref("browser.uitour.enabled", false);
|
| 121 |
+
user_pref("browser.newtabpage.activity-stream.feeds.telemetry", false);
|
| 122 |
+
user_pref("datareporting.policy.dataSubmissionEnabled", false);
|
| 123 |
+
user_pref("app.normandy.enabled", false);
|
| 124 |
+
user_pref("app.update.enabled", false);
|
| 125 |
+
user_pref("app.update.auto", false);
|
| 126 |
+
"""
|
| 127 |
+
|
| 128 |
+
def _ensure_firefox_profile(user_id: str, display: str) -> str:
|
| 129 |
+
"""
|
| 130 |
+
ูููุดุฆ (ุฃู ููุนูุฏ ุงุณุชุฎุฏุงู
) ุจุฑููุงูู Firefox ู
ุฎุตุต ููุธูู ููุฐุง ุงูู
ุณุชุฎุฏู
ุ
|
| 131 |
+
ู
ุน ุฅุนุฏุงุฏุงุช ุชุนุทูู ุงุณุชุฑุฌุงุน ุงูุฌูุณุฉ (crash recovery) ููุงุฆูุงู.
|
| 132 |
+
ููุนูุฏ ุงูู
ุณุงุฑ ุงููุงู
ู ููุจุฑููุงูู.
|
| 133 |
+
"""
|
| 134 |
+
safe_id = re.sub(r"[^a-zA-Z0-9_.-]", "_", user_id) or "anon"
|
| 135 |
+
profile_dir = os.path.expanduser(f"~/.zai_ff_profiles/{safe_id}")
|
| 136 |
+
try:
|
| 137 |
+
os.makedirs(profile_dir, exist_ok=True)
|
| 138 |
+
prefs_path = os.path.join(profile_dir, "user.js")
|
| 139 |
+
with open(prefs_path, "w", encoding="utf-8") as f:
|
| 140 |
+
f.write(FIREFOX_PROFILE_PREFS)
|
| 141 |
+
except Exception as e:
|
| 142 |
+
print(f"[profile] โ ๏ธ failed to prepare profile for {user_id}: {e}")
|
| 143 |
+
return profile_dir
|
| 144 |
+
|
| 145 |
+
|
| 146 |
+
def _wipe_firefox_session_data(profile_dir: str):
|
| 147 |
+
"""
|
| 148 |
+
ูู
ุณุญ ู
ููุงุช ุงูุฌูุณุฉ ุงููุงุณุฏุฉ (sessionstore) + ุฃู lock ู
ุชุจููู.
|
| 149 |
+
ูุฐุง ุถุฑูุฑู ูุฃู ู
ุฌุฑุฏ ุชุนุทูู session restore ูู user.js ูุง ูู
ุณุญ ู
ููุงุช
|
| 150 |
+
ุฌูุณุฉ ุณุงุจูุฉ ู
ูุฌูุฏุฉ ุจุงููุนู ุนูู ุงููุฑุต ู
ู ูุจู ุชูุนูู ูุฐู ุงูุฅุนุฏุงุฏุงุช.
|
| 151 |
+
"""
|
| 152 |
+
try:
|
| 153 |
+
subprocess.run(
|
| 154 |
+
f"rm -f '{profile_dir}'/lock '{profile_dir}'/.parentlock "
|
| 155 |
+
f"'{profile_dir}'/sessionstore.jsonlz4 "
|
| 156 |
+
f"'{profile_dir}'/sessionstore-backups/*.jsonlz4 "
|
| 157 |
+
f"'{profile_dir}'/sessionCheckpoints.json 2>/dev/null",
|
| 158 |
+
shell=True, timeout=5, capture_output=True
|
| 159 |
+
)
|
| 160 |
+
except Exception:
|
| 161 |
+
pass
|
| 162 |
+
|
| 163 |
|
| 164 |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 165 |
# โโ Xvfb Management (per-display) โโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
|
| 248 |
def _kill_display_processes(display: str):
|
| 249 |
"""ููุชู ูู ุงูุนู
ููุงุช ุงูู
ุฑุชุจุทุฉ ุจู display ู
ุนูู."""
|
| 250 |
env_d = {**os.environ, "DISPLAY": display}
|
| 251 |
+
# ูุชู ุงูู
ุชุตูุญ โ SIGKILL ู
ุจุงุดุฑ (-9) ูุชูุงุฏู ุฃู ุญุงูุฉ ุฅุบูุงู ูุตูู ุชูุณุฌููู
|
| 252 |
+
# ูุงุญูุงู ูุชุญุทูู
(crash) ุฏุงุฎู Firefox ูุชููุชุฌ ุดุงุดุฉ "Restore Session"
|
| 253 |
for b in ["firefox", "firefox-esr", "chromium", "chrome"]:
|
| 254 |
try:
|
| 255 |
subprocess.run(
|
| 256 |
+
["pkill", "-9", "-f", f"[{b[0]}]{b[1:]}.*{display}"],
|
| 257 |
timeout=3, capture_output=True
|
| 258 |
)
|
| 259 |
except Exception:
|
|
|
|
| 319 |
display = sess["display"]
|
| 320 |
print(f"[reset] ๐ Resetting computer for user '{user_id}' on {display}")
|
| 321 |
|
| 322 |
+
# ูุชู ุงูู
ุชุตูุญ โ SIGKILL ู
ุจุงุดุฑ (ุจุฏู terminate ุงููุทูู) ูุฃู ุงูุฃุฎูุฑ ูุฏ
|
| 323 |
+
# ูุชุฑู ูุงูุฑูููุณ ูู ุญุงูุฉ ูุตู-ู
ุบููุฉ ุชูุณุฌููู ูุชุญุทูู
(crash) ูู ุงูู
ุฑุฉ
|
| 324 |
+
# ุงููุงุฏู
ุฉุ ููุฐุง ุจุงูุถุจุท ู
ุง ูููุชุฌ ุดุงุดุฉ "Restore Session" ูุงุญูุงู.
|
| 325 |
+
browser_proc = sess.get("browser_proc")
|
| 326 |
+
if browser_proc:
|
| 327 |
+
try:
|
| 328 |
+
browser_proc.kill()
|
| 329 |
+
browser_proc.wait(timeout=3)
|
| 330 |
+
except Exception:
|
| 331 |
+
pass
|
| 332 |
sess["browser_proc"] = None
|
| 333 |
|
| 334 |
# ูุชู Xvfb
|
|
|
|
| 338 |
# ุชูุธูู ุดุงู
ู ููุฐุง ุงูู display
|
| 339 |
_kill_display_processes(display)
|
| 340 |
|
| 341 |
+
# โโ ุชูุธูู ุดุงู
ู ูุจูุงูุงุช ุฌูุณุฉ Firefox ุงููุงุณุฏุฉ (ุงูุณุจุจ ุงูุฌุฐุฑู ูุดุงุดุฉ
|
| 342 |
+
# "Restore Session") โ ููุณ ููุท lock files ุจู sessionstore ูุงู
ูุงูุ
|
| 343 |
+
# ูู ูู ู
ู ุงูุจุฑููุงูู ุงูุงูุชุฑุงุถู ูุฃู ุจุฑููุงูู ู
ุฎุตุต ููุฐุง ุงูู
ุณุชุฎุฏู
โโ
|
| 344 |
try:
|
| 345 |
subprocess.run(
|
| 346 |
+
"rm -f ~/.mozilla/firefox/*/lock ~/.mozilla/firefox/*/.parentlock "
|
| 347 |
+
"~/.mozilla/firefox/*/sessionstore.jsonlz4 "
|
| 348 |
+
"~/.mozilla/firefox/*/sessionstore-backups/*.jsonlz4 "
|
| 349 |
+
"~/.mozilla/firefox/*/sessionCheckpoints.json 2>/dev/null",
|
| 350 |
shell=True, timeout=5, capture_output=True
|
| 351 |
)
|
| 352 |
except Exception:
|
| 353 |
pass
|
| 354 |
+
safe_id = re.sub(r"[^a-zA-Z0-9_.-]", "_", user_id) or "anon"
|
| 355 |
+
custom_profile = os.path.expanduser(f"~/.zai_ff_profiles/{safe_id}")
|
| 356 |
+
_wipe_firefox_session_data(custom_profile)
|
| 357 |
|
| 358 |
# ุชุดุบูู Xvfb ุฌุฏูุฏ (ุฎุงุฑุฌ ุงูู lock ูุฃู start_xvfb ูุณุชุบุฑู ููุชุงู)
|
| 359 |
new_proc = await asyncio.to_thread(_start_xvfb, display)
|
|
|
|
| 1114 |
await send({"type": "ack", "action": "open_app"})
|
| 1115 |
return
|
| 1116 |
if "firefox" in cmd.lower():
|
| 1117 |
+
profile_dir = _ensure_firefox_profile(sess["user_id"], display)
|
| 1118 |
+
# ูุชู ููุฑู ูููู (SIGKILL) ุจุฏู pkill ุงููุทูู: ูู
ูุน ูุงูุฑูููุณ ู
ู
|
| 1119 |
+
# "ุงูุชูุงุท" ุญุงูุฉ ูุตู-ู
ูุชูุญุฉ ุชูุณุฌููู ูุงุญูุงู ูุชุญุทูู
(crash) ูููุชุฌ
|
| 1120 |
+
# ุดุงุดุฉ "Restore Session" ูู ุงูู
ุฑุฉ ุงููุงุฏู
ุฉ.
|
| 1121 |
await run_cmd(
|
| 1122 |
+
"pkill -9 -f '[f]irefox' 2>/dev/null; sleep 0.6; echo CLEANED",
|
|
|
|
|
|
|
| 1123 |
display, timeout=8
|
| 1124 |
)
|
| 1125 |
+
_wipe_firefox_session_data(profile_dir)
|
| 1126 |
+
# ุญูู --profile ุฏุงุฎู ุฃู
ุฑ ูุงูุฑูููุณ (ุฅู ูู
ููู ู
ุญูููุงู ู
ุณุจูุงู)
|
| 1127 |
+
if "--profile" not in cmd and "-P " not in cmd:
|
| 1128 |
+
cmd = cmd.replace("firefox", f"firefox --profile '{profile_dir}' --no-remote", 1)
|
| 1129 |
env = {**os.environ, "DISPLAY": display}
|
| 1130 |
proc = subprocess.Popen(cmd, shell=True, env=env,
|
| 1131 |
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
|
|
| 1144 |
# โโ open_browser โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1145 |
elif action == "open_browser":
|
| 1146 |
url = _safe_search(data.get("url", "") or "about:blank")
|
| 1147 |
+
profile_dir = _ensure_firefox_profile(sess["user_id"], display)
|
| 1148 |
+
# ูุชู ููุฑู ูููู (SIGKILL) ุจุฏู pkill ุงููุทูู โ ูู
ูุน ุชุณุฌูู ุญุงูุฉ
|
| 1149 |
+
# "ุชุญุทูู
" ูู sessionstoreุ ููู ุงูุณุจุจ ุงูุฌุฐุฑู ูุดุงุดุฉ "Restore Session"
|
| 1150 |
+
# ุงูุชู ุชุญุฌุจ ุงูู
ุญุชูู ุงููุนูู ูุชููุชูุท ูููุทุฉ ุดุงุดุฉ ุตุงูุญุฉ (ุบูุฑ ุณูุฏุงุก)
|
| 1151 |
+
# ููููุง ููุณุช ุงูุตูุญุฉ ุงูู
ุทููุจุฉ.
|
| 1152 |
await run_cmd(
|
| 1153 |
+
"pkill -9 -f '[f]irefox' 2>/dev/null; sleep 0.6; echo CLEANED",
|
|
|
|
|
|
|
| 1154 |
display, timeout=8
|
| 1155 |
)
|
| 1156 |
+
_wipe_firefox_session_data(profile_dir)
|
| 1157 |
env = {**os.environ, "DISPLAY": display}
|
| 1158 |
proc = subprocess.Popen(
|
| 1159 |
+
[BROWSER, "--profile", profile_dir, "--no-remote", url], env=env,
|
| 1160 |
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
|
| 1161 |
)
|
| 1162 |
with _display_lock:
|