mirror of
https://github.com/SteamDeckHomebrew/decky-loader.git
synced 2026-07-11 21:51:57 +00:00
Add CEF Remote Debugging toggle (#129)
* feat: add CEF Remote Debugging toggle * feat: disable remote debugger on startup * refactor: stop debugger instead of disable * feat: add option to allow remote debugging by default Co-authored-by: TrainDoctor <traindoctor@protonmail.com>
This commit is contained in:
@@ -2,11 +2,15 @@ import certifi
|
|||||||
import ssl
|
import ssl
|
||||||
import uuid
|
import uuid
|
||||||
import re
|
import re
|
||||||
|
import subprocess
|
||||||
|
|
||||||
from aiohttp.web import middleware, Response
|
from aiohttp.web import middleware, Response
|
||||||
from subprocess import check_output
|
from subprocess import check_output
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
|
|
||||||
|
REMOTE_DEBUGGER_UNIT = "steam-web-debug-portforward.service"
|
||||||
|
|
||||||
# global vars
|
# global vars
|
||||||
csrf_token = str(uuid.uuid4())
|
csrf_token = str(uuid.uuid4())
|
||||||
ssl_ctx = ssl.create_default_context(cafile=certifi.where())
|
ssl_ctx = ssl.create_default_context(cafile=certifi.where())
|
||||||
@@ -63,3 +67,17 @@ def get_user_group() -> str:
|
|||||||
if group == None:
|
if group == None:
|
||||||
raise ValueError("helpers.get_user_group method called before group variable was set. Run helpers.set_user_group first.")
|
raise ValueError("helpers.get_user_group method called before group variable was set. Run helpers.set_user_group first.")
|
||||||
return group
|
return group
|
||||||
|
|
||||||
|
async def is_systemd_unit_active(unit_name: str) -> bool:
|
||||||
|
res = subprocess.run(["systemctl", "is-active", unit_name], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||||
|
return res.returncode == 0
|
||||||
|
|
||||||
|
async def stop_systemd_unit(unit_name: str) -> subprocess.CompletedProcess:
|
||||||
|
cmd = ["systemctl", "stop", unit_name]
|
||||||
|
|
||||||
|
return subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||||
|
|
||||||
|
async def start_systemd_unit(unit_name: str) -> subprocess.CompletedProcess:
|
||||||
|
cmd = ["systemctl", "start", unit_name]
|
||||||
|
|
||||||
|
return subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||||
|
|||||||
+8
-2
@@ -13,7 +13,7 @@ from subprocess import call
|
|||||||
|
|
||||||
# local modules
|
# local modules
|
||||||
from browser import PluginBrowser
|
from browser import PluginBrowser
|
||||||
from helpers import csrf_middleware, get_csrf_token, get_user, get_user_group, set_user, set_user_group
|
from helpers import csrf_middleware, get_csrf_token, get_user, get_user_group, set_user, set_user_group, stop_systemd_unit, REMOTE_DEBUGGER_UNIT
|
||||||
from injector import inject_to_tab, tab_has_global_var
|
from injector import inject_to_tab, tab_has_global_var
|
||||||
from loader import Loader
|
from loader import Loader
|
||||||
from updater import Updater
|
from updater import Updater
|
||||||
@@ -28,8 +28,9 @@ set_user_group()
|
|||||||
USER = get_user()
|
USER = get_user()
|
||||||
GROUP = get_user_group()
|
GROUP = get_user_group()
|
||||||
HOME_PATH = "/home/"+USER
|
HOME_PATH = "/home/"+USER
|
||||||
|
HOMEBREW_PATH = HOME_PATH+"/homebrew"
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"plugin_path": getenv("PLUGIN_PATH", HOME_PATH+"/homebrew/plugins"),
|
"plugin_path": getenv("PLUGIN_PATH", HOMEBREW_PATH+"/plugins"),
|
||||||
"chown_plugin_path": getenv("CHOWN_PLUGIN_PATH", "1") == "1",
|
"chown_plugin_path": getenv("CHOWN_PLUGIN_PATH", "1") == "1",
|
||||||
"server_host": getenv("SERVER_HOST", "127.0.0.1"),
|
"server_host": getenv("SERVER_HOST", "127.0.0.1"),
|
||||||
"server_port": int(getenv("SERVER_PORT", "1337")),
|
"server_port": int(getenv("SERVER_PORT", "1337")),
|
||||||
@@ -47,6 +48,9 @@ async def chown_plugin_dir(_):
|
|||||||
if code_chown != 0 or code_chmod != 0:
|
if code_chown != 0 or code_chmod != 0:
|
||||||
logger.error(f"chown/chmod exited with a non-zero exit code (chown: {code_chown}, chmod: {code_chmod})")
|
logger.error(f"chown/chmod exited with a non-zero exit code (chown: {code_chown}, chmod: {code_chmod})")
|
||||||
|
|
||||||
|
def remote_debugging_allowed():
|
||||||
|
return path.exists(HOMEBREW_PATH + "/allow_remote_debugging")
|
||||||
|
|
||||||
class PluginManager:
|
class PluginManager:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.loop = get_event_loop()
|
self.loop = get_event_loop()
|
||||||
@@ -66,6 +70,8 @@ class PluginManager:
|
|||||||
self.web_app.on_startup.append(chown_plugin_dir)
|
self.web_app.on_startup.append(chown_plugin_dir)
|
||||||
self.loop.create_task(self.loader_reinjector())
|
self.loop.create_task(self.loader_reinjector())
|
||||||
self.loop.create_task(self.load_plugins())
|
self.loop.create_task(self.load_plugins())
|
||||||
|
if not remote_debugging_allowed():
|
||||||
|
self.loop.create_task(stop_systemd_unit(REMOTE_DEBUGGER_UNIT))
|
||||||
self.loop.set_exception_handler(self.exception_handler)
|
self.loop.set_exception_handler(self.exception_handler)
|
||||||
self.web_app.add_routes([get("/auth/token", self.get_auth_token)])
|
self.web_app.add_routes([get("/auth/token", self.get_auth_token)])
|
||||||
|
|
||||||
|
|||||||
+17
-1
@@ -5,6 +5,7 @@ from aiohttp import ClientSession, web
|
|||||||
|
|
||||||
from injector import inject_to_tab
|
from injector import inject_to_tab
|
||||||
import helpers
|
import helpers
|
||||||
|
import subprocess
|
||||||
|
|
||||||
class Utilities:
|
class Utilities:
|
||||||
def __init__(self, context) -> None:
|
def __init__(self, context) -> None:
|
||||||
@@ -16,7 +17,10 @@ class Utilities:
|
|||||||
"confirm_plugin_install": self.confirm_plugin_install,
|
"confirm_plugin_install": self.confirm_plugin_install,
|
||||||
"execute_in_tab": self.execute_in_tab,
|
"execute_in_tab": self.execute_in_tab,
|
||||||
"inject_css_into_tab": self.inject_css_into_tab,
|
"inject_css_into_tab": self.inject_css_into_tab,
|
||||||
"remove_css_from_tab": self.remove_css_from_tab
|
"remove_css_from_tab": self.remove_css_from_tab,
|
||||||
|
"allow_remote_debugging": self.allow_remote_debugging,
|
||||||
|
"disallow_remote_debugging": self.disallow_remote_debugging,
|
||||||
|
"remote_debugging_allowed": self.remote_debugging_allowed
|
||||||
}
|
}
|
||||||
|
|
||||||
if context:
|
if context:
|
||||||
@@ -133,3 +137,15 @@ class Utilities:
|
|||||||
"success": False,
|
"success": False,
|
||||||
"result": e
|
"result": e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def remote_debugging_allowed(self):
|
||||||
|
return await helpers.is_systemd_unit_active(helpers.REMOTE_DEBUGGER_UNIT)
|
||||||
|
|
||||||
|
async def allow_remote_debugging(self):
|
||||||
|
await helpers.start_systemd_unit(helpers.REMOTE_DEBUGGER_UNIT)
|
||||||
|
return True
|
||||||
|
|
||||||
|
async def disallow_remote_debugging(self):
|
||||||
|
await helpers.stop_systemd_unit(helpers.REMOTE_DEBUGGER_UNIT)
|
||||||
|
return True
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import { Field, ToggleField } from 'decky-frontend-lib';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { FaBug } from 'react-icons/fa';
|
||||||
|
|
||||||
|
export default function RemoteDebuggingSettings() {
|
||||||
|
const [allowRemoteDebugging, setAllowRemoteDebugging] = useState<boolean>(false);
|
||||||
|
useEffect(() => {
|
||||||
|
(async () => {
|
||||||
|
const res = (await window.DeckyPluginLoader.callServerMethod('remote_debugging_allowed')) as { result: boolean };
|
||||||
|
setAllowRemoteDebugging(res.result);
|
||||||
|
})();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Field
|
||||||
|
label="Allow Remote CEF Debugging"
|
||||||
|
description={
|
||||||
|
<span style={{ whiteSpace: 'pre-line' }}>
|
||||||
|
Allow unauthenticated access to the CEF debugger to anyone in your network
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
icon={<FaBug style={{ display: 'block' }} />}
|
||||||
|
>
|
||||||
|
<ToggleField
|
||||||
|
checked={allowRemoteDebugging}
|
||||||
|
onChange={(toggleValue) => {
|
||||||
|
setAllowRemoteDebugging(toggleValue);
|
||||||
|
if (toggleValue) window.DeckyPluginLoader.callServerMethod('allow_remote_debugging');
|
||||||
|
else window.DeckyPluginLoader.callServerMethod('disallow_remote_debugging');
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Field>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ import { useState } from 'react';
|
|||||||
import { FaShapes } from 'react-icons/fa';
|
import { FaShapes } from 'react-icons/fa';
|
||||||
|
|
||||||
import { installFromURL } from '../../../store/Store';
|
import { installFromURL } from '../../../store/Store';
|
||||||
|
import RemoteDebuggingSettings from './RemoteDebugging';
|
||||||
import UpdaterSettings from './Updater';
|
import UpdaterSettings from './Updater';
|
||||||
|
|
||||||
export default function GeneralSettings() {
|
export default function GeneralSettings() {
|
||||||
@@ -20,6 +21,7 @@ export default function GeneralSettings() {
|
|||||||
/>
|
/>
|
||||||
</Field> */}
|
</Field> */}
|
||||||
<UpdaterSettings />
|
<UpdaterSettings />
|
||||||
|
<RemoteDebuggingSettings />
|
||||||
<Field
|
<Field
|
||||||
label="Manual plugin install"
|
label="Manual plugin install"
|
||||||
description={<TextField label={'URL'} value={pluginURL} onChange={(e) => setPluginURL(e?.target.value)} />}
|
description={<TextField label={'URL'} value={pluginURL} onChange={(e) => setPluginURL(e?.target.value)} />}
|
||||||
|
|||||||
Reference in New Issue
Block a user