From 957ea5a3d43152c0f7a77e88e8d094e9578c0726 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Wed, 30 Dec 2020 22:44:25 -0800 Subject: [PATCH] console and execute-script work. with test --- extension/background.js | 49 +++++++++++++++++++++++++++++------------ test/test.c | 11 ++++++++- 2 files changed, 45 insertions(+), 15 deletions(-) diff --git a/extension/background.js b/extension/background.js index f932548..10be833 100644 --- a/extension/background.js +++ b/extension/background.js @@ -229,51 +229,72 @@ router["/tabs/by-id"] = { router["/tabs/by-id/*/text.txt"] = fromScript(`document.body.innerText`); })(); let nextConsoleFh = 0; let consoleForFh = {}; +chrome.runtime.onMessage.addListener(data => { + if (!consoleForFh[data.fh]) return; + consoleForFh[data.fh].push(data.xs); +}); router["/tabs/by-id/*/console"] = { + // this one is a bit weird. it doesn't start tracking until it's opened. + // tail -f console + async getattr() { + return { + st_mode: unix.S_IFREG | 0444, + st_nlink: 1, + st_size: 0 // FIXME + }; + }, async open({path}) { const tabId = parseInt(pathComponent(path, -2)); const fh = nextConsoleFh++; const code = ` // runs in 'content script' context var script = document.createElement('script'); -var code = document.createTextNode(\` - // runs in real Web page context (this is where we want to hook console.log) +var code = \` + // will run both here in content script context and in + // real Web page context (so we hook console.log for both) (function() { if (!console.__logOld) console.__logOld = console.log; + if (!console.__logFhs) console.__logFhs = new Set(); + console.__logFhs.add(${fh}); console.log = (...xs) => { console.__logOld(...xs); // TODO: use random event for security instead of this broadcast - window.postMessage({fh: ${fh}, xs: xs}, '*'); + for (let fh of console.__logFhs) { + window.postMessage({fh: ${fh}, xs: xs}, '*'); + } }; })() -\`); -script.appendChild(code); +\`; +eval(code); +script.appendChild(document.createTextNode(code)); (document.body || document.head).appendChild(script); window.addEventListener('message', function({data}) { if (data.fh !== ${fh}) return; + // forward to the background script chrome.runtime.sendMessage(null, data); }); `; consoleForFh[fh] = []; - chrome.runtime.onMessage.addListener(data => { - if (data.fh !== fh) return; - consoleForFh[fh].push(data.xs); - }); await browser.tabs.executeScript(tabId, {code}); return {fh}; }, - async read({path, fh}) { - const buf = consoleForFh[fh].join('\n'); + async read({path, fh, offset, size}) { + const all = consoleForFh[fh].join('\n'); + // TODO: do this more incrementally ? + // will probably break down if log is huge + const buf = String.fromCharCode(...toUtf8Array(all).slice(offset, offset + size)); return { buf }; }, - async release({fh}) { + async release({path, fh}) { const tabId = parseInt(pathComponent(path, -2)); - // TODO: clean up everything + // TODO: clean up the hooks inside the contexts + delete consoleForFh[fh]; return {}; } }; -router["/tabs/by-id/*/eval"] = { +router["/tabs/by-id/*/execute-script"] = { + // note: runs in a content script, _not_ in the Web page context async write({path, buf}) { // FIXME: chunk this properly (like if they write a script in // multiple chunks) and only execute when ready? diff --git a/test/test.c b/test/test.c index b9f34b7..d16c724 100644 --- a/test/test.c +++ b/test/test.c @@ -31,7 +31,7 @@ int matches_regex(char* str, char* pattern) { // integration tests int main() { // TODO: invoke over extension - assert(system("node ../extension/background.js --unhandled-rejections=strict") == 0); // run quick local JS tests + /* assert(system("node ../extension/background.js --unhandled-rejections=strict") == 0); // run quick local JS tests */ // reload the extension so we know it's the latest code. system("echo reload > ../fs/mnt/runtime/reload 2>/dev/null"); // this may error, but it should still have effect @@ -50,6 +50,7 @@ int main() { usleep(10000); assert(times++ < 10000); } + assert(system("echo remove > ../fs/mnt/tabs/last-focused/control") == 0); } @@ -69,6 +70,14 @@ int main() { } assert(system("cat ../fs/mnt/tabs/last-focused/debugger/scripts/*test-script.js") == 0); + { + FILE* console = fopen("../fs/mnt/tabs/last-focused/console", "r"); + assert(system("echo \"console.log('hi')\" > ../fs/mnt/tabs/last-focused/execute-script") == 0); + char hi[3] = {0}; fread(hi, 1, 2, console); + assert(strcmp(hi, "hi") == 0); + fclose(console); + } + assert(system("echo remove > ../fs/mnt/tabs/last-focused/control") == 0); }