Created
August 25, 2022 12:18
-
-
Save tkon99/eac47bd5a7458b6be3b46177bf7162a5 to your computer and use it in GitHub Desktop.
Browsy - A proof of concept for a highly compressed web browser that can be used over any connection
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Browsy</title> | |
<script src="/socket.io/socket.io.js"></script> | |
<script> | |
var socket = io(); | |
// var viewer = document.getElementById("viewer"); | |
socket.on("page", (...data) => { | |
document.getElementById("viewer").setAttribute("src", data); | |
}); | |
document.addEventListener("DOMContentLoaded", function() { | |
document.getElementById("viewer").addEventListener('click', (e) => { | |
e.preventDefault(); | |
socket.emit("click", {x: e.offsetX, y: e.offsetY}); | |
document.getElementById("keyboard").focus(); | |
}); | |
document.getElementById("submit").addEventListener('click', (e) => { | |
socket.emit("type", {text: document.getElementById("keyboard").value}); | |
document.getElementById("keyboard").value = ""; | |
document.getElementById("keyboard").focus(); | |
}); | |
document.getElementById("navigate").addEventListener('click', (e) => { | |
socket.emit("navigate", {text: document.getElementById("keyboard").value}); | |
document.getElementById("keyboard").value = ""; | |
document.getElementById("keyboard").focus(); | |
}); | |
document.getElementById("scrollUp").addEventListener('click', (e) => { | |
socket.emit("scrollUp"); | |
document.getElementById("keyboard").focus(); | |
}); | |
document.getElementById("scrollDown").addEventListener('click', (e) => { | |
socket.emit("scrollDown"); | |
document.getElementById("keyboard").focus(); | |
}); | |
document.getElementById("refreshImage").addEventListener('click', (e) => { | |
socket.emit("refreshImage"); | |
document.getElementById("keyboard").focus(); | |
}); | |
}); | |
</script> | |
</head> | |
<body> | |
<h1>Browsy</h1> | |
<img src="" id="viewer" style="cursor:pointer"/><br> | |
<input type="text" id="keyboard"/><button id="submit">Type</button><button id="navigate">Navigate</button><br> | |
<button id="scrollUp">↑</button><button id="scrollDown">↓</button><button id="refreshImage">Update image</button> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const puppeteer = require('puppeteer'); | |
const Jimp = require('jimp'); | |
const express = require('express'); | |
const app = express(); | |
const http = require('http'); | |
const server = http.createServer(app); | |
const { Server } = require("socket.io"); | |
const io = new Server(server, { | |
pingTimeout: 5*60*1000 // Preserve Session for 5 minutes | |
}); | |
async function createSession(browser){ | |
const context = await browser.createIncognitoBrowserContext(); | |
const page = await context.newPage(); | |
await page.setViewport({ | |
width: 320, | |
height: 510, | |
deviceScaleFactor: 4 | |
}); | |
await page.goto('https://duckduckgo.com'); | |
return page; | |
} | |
async function screenshotSession(page){ | |
let screenshot = await page.screenshot(); | |
let image = await Jimp.read(screenshot); | |
let msg = await image.quality(20).resize(320, Jimp.AUTO, Jimp.RESIZE_NEAREST_NEIGHBOR).quality(10).getBase64Async('image/jpeg'); | |
return msg; | |
} | |
async function sessionClick(socket, page, data){ | |
await page.mouse.click(data.x, data.y, { button: 'left' }); | |
let msg = await screenshotSession(page); | |
socket.emit("page", msg); | |
return | |
} | |
async function sessionType(socket, page, data){ | |
await page.keyboard.type(data.text); | |
let msg = await screenshotSession(page); | |
socket.emit("page", msg); | |
return | |
} | |
async function sessionScroll(socket, page, direction){ | |
if(direction == -1){ | |
await page.evaluate(_ => { | |
window.scrollBy(0, -0.5*window.innerHeight); | |
}); | |
}else{ | |
await page.evaluate(_ => { | |
window.scrollBy(0, 0.5*window.innerHeight); | |
}); | |
} | |
let msg = await screenshotSession(page); | |
socket.emit("page", msg); | |
} | |
async function sessionNav(socket, page, data){ | |
await page.goto(data.text); | |
let msg = await screenshotSession(page); | |
socket.emit("page", msg); | |
} | |
(async () => { | |
const browser = await puppeteer.launch(); | |
app.get('/', (req, res) => { | |
res.sendFile(__dirname + "/client.html"); | |
}); | |
io.on('connection', (socket) => { | |
console.log('New connection.'); | |
createSession(browser).then((Session) => { | |
screenshotSession(Session).then((msg) => { | |
socket.emit("page", msg); | |
}); | |
socket.on("click", (data) => { | |
console.log(data); | |
sessionClick(socket, Session, data); | |
}); | |
socket.on("type", (data) => { | |
sessionType(socket, Session, data); | |
}); | |
socket.on("scrollUp", (data) => { | |
sessionScroll(socket, Session, -1); | |
}); | |
socket.on("scrollDown", (data) => { | |
sessionScroll(socket, Session, 1); | |
}); | |
socket.on("refreshImage", (data) => { | |
screenshotSession(Session).then((msg) => { | |
socket.emit("page", msg); | |
}); | |
}); | |
socket.on("navigate", (data) => { | |
sessionNav(socket, Session, data); | |
}); | |
// Close out the session | |
socket.conn.on("close", (reason) => { | |
console.log("Destroyed Session for "+socket.id); | |
Session.browserContext().close(); | |
}); | |
}); | |
}); | |
server.listen(3000, () => { | |
console.log('listening on *:3000'); | |
}); | |
// await browser.close(); | |
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "browsy", | |
"version": "1.0.0", | |
"description": "", | |
"main": "index.js", | |
"scripts": { | |
"test": "echo \"Error: no test specified\" && exit 1" | |
}, | |
"author": "", | |
"license": "ISC", | |
"dependencies": { | |
"express": "^4.18.1", | |
"jimp": "^0.16.1", | |
"puppeteer": "^16.2.0", | |
"socket.io": "^4.5.1" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment