summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorWerWolv <werwolv98@gmail.com>2022-03-31 08:31:03 +0200
committerWerWolv <werwolv98@gmail.com>2022-03-31 08:31:03 +0200
commita38e03094b49fdc44389d4a558e55108d6db827a (patch)
tree74eb1e11de56d1593d651ed623a959d715e81f30 /src
parent807acfa8b464584b76567e9c006a6a4c81589645 (diff)
downloaddecky-loader-a38e03094b49fdc44389d4a558e55108d6db827a.tar.gz
decky-loader-a38e03094b49fdc44389d4a558e55108d6db827a.zip
sys: Added initial code injection logic
Diffstat (limited to 'src')
-rw-r--r--src/main.rs120
-rw-r--r--src/plugin_page.js26
2 files changed, 146 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 00000000..90d23a26
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,120 @@
+use std::fmt::{Debug, Display, Formatter};
+use hyper::{Client, Uri};
+use hyper::body::Buf;
+use serde::{ Serialize, Deserialize };
+use serde_json;
+use tungstenite::Message;
+
+type TokioResult<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
+
+enum AppError {
+ ContentNotFound
+}
+
+impl Debug for AppError {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ let message = match self {
+ AppError::ContentNotFound => "Content not found"
+ };
+
+ write!(f, "{}", message)
+ }
+}
+
+impl Display for AppError {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{}", self)
+ }
+}
+
+unsafe impl Send for AppError { }
+unsafe impl Sync for AppError { }
+
+impl std::error::Error for AppError { }
+
+#[allow(non_snake_case)]
+#[allow(dead_code)]
+#[derive(Deserialize)]
+struct WebContent {
+ description: String,
+ devtoolsFrontendUrl: String,
+ id: String,
+ title: String,
+ r#type: String,
+ url: String,
+ webSocketDebuggerUrl: String
+}
+
+#[allow(non_snake_case)]
+#[allow(dead_code)]
+#[derive(Serialize)]
+struct DebuggerCommandParams {
+ expression: String,
+ userGesture: bool
+}
+
+#[allow(non_snake_case)]
+#[allow(dead_code)]
+#[derive(Serialize)]
+struct DebuggerCommand {
+ id: u32,
+ method: String,
+ params: DebuggerCommandParams
+}
+
+async fn get_web_content(url: Uri) -> TokioResult<Vec<WebContent>> {
+ let client = Client::new();
+ let response = client.get(url).await?;
+ let body = hyper::body::aggregate(response).await?;
+
+ let data = String::from(std::str::from_utf8(body.chunk())?);
+
+ Ok(serde_json::from_str(data.as_str())?)
+}
+
+#[tokio::main]
+async fn main() -> TokioResult<()> {
+ let url = "http://127.0.0.1:8080/json".parse::<hyper::Uri>().unwrap();
+
+ let contents = get_web_content(url).await?;
+
+ println!("Available Content:");
+ for content in &contents {
+ println!(" {}", content.title);
+ }
+
+ let mut quick_access_debug_url: Option<String> = None;
+ for content in &contents {
+ if content.title == "QuickAccess" {
+ quick_access_debug_url = Some(content.webSocketDebuggerUrl.clone());
+ }
+ }
+
+ if let Some(url) = quick_access_debug_url {
+
+ let (mut socket, _) = tungstenite::connect(url)?;
+
+ let command = DebuggerCommand {
+ id: 1,
+ method: String::from("Runtime.evaluate"),
+ params: DebuggerCommandParams {
+ expression: String::from(include_str!("plugin_page.js")),
+ userGesture: true
+ }
+ };
+
+ socket.write_message(Message::Text(serde_json::to_string(&command)?))?;
+
+ let response = socket.read_message()?;
+
+ println!("{}", response);
+
+ socket.close(None)?;
+
+ } else {
+ return Err(AppError::ContentNotFound.into());
+ }
+
+
+ Ok(())
+} \ No newline at end of file
diff --git a/src/plugin_page.js b/src/plugin_page.js
new file mode 100644
index 00000000..50dc419c
--- /dev/null
+++ b/src/plugin_page.js
@@ -0,0 +1,26 @@
+(function () {
+ const PLUGIN_ICON = `
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-plugin" viewBox="0 0 16 16">
+ <path fill-rule="evenodd" d="M1 8a7 7 0 1 1 2.898 5.673c-.167-.121-.216-.406-.002-.62l1.8-1.8a3.5 3.5 0 0 0
+ 4.572-.328l1.414-1.415a.5.5 0 0 0 0-.707l-.707-.707 1.559-1.563a.5.5 0 1 0-.708-.706l-1.559 1.562-1.414-1.414
+ 1.56-1.562a.5.5 0 1 0-.707-.706l-1.56 1.56-.707-.706a.5.5 0 0 0-.707 0L5.318 5.975a3.5 3.5 0 0 0-.328
+ 4.571l-1.8 1.8c-.58.58-.62 1.6.121 2.137A8 8 0 1 0 0 8a.5.5 0 0 0 1 0Z"/>
+ </svg>
+ `;
+
+ function inject() {
+ let tabs = document.getElementsByClassName("quickaccessmenu_TabContentColumn_2z5NL Panel Focusable")[0];
+ tabs.children[tabs.children.length - 1].innerHTML = PLUGIN_ICON;
+
+ let pages = document.getElementsByClassName("quickaccessmenu_AllTabContents_2yKG4 quickaccessmenu_Down_3rR0o")[0];
+ let pluginPage = pages.children[pages.children.length - 1];
+ pluginPage.innerHTML = "Hello from Rust!";
+ }
+
+ let injector = setInterval(function () {
+ if (document.hasFocus()) {
+ inject();
+ clearInterval(injector);
+ }
+ }, 100);
+})(); \ No newline at end of file