aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOmar Rizwan <omar@omar.website>2020-12-29 03:52:17 -0800
committerOmar Rizwan <omar@omar.website>2020-12-29 03:52:17 -0800
commit705b245be5ea7e69f04c1ab370962de054800bb0 (patch)
treed2ffb73fcb548855d45aae87cf79ee3e71829502
parent44c8dfcec6e04a19ef78e2de38c97f49f9fcb8d5 (diff)
prevent explosion of scriptsForTab!
-rw-r--r--extension/background.js68
-rw-r--r--tabfs.md57
-rw-r--r--test/test.c3
3 files changed, 81 insertions, 47 deletions
diff --git a/extension/background.js b/extension/background.js
index 4de9b67..51b4043 100644
--- a/extension/background.js
+++ b/extension/background.js
@@ -52,48 +52,48 @@ async function detachDebugger(tabId) {
else { resolve(); }
}));
}
-const TabManager = {
- debugTab: async function(tabId) {
- // meant to be higher-level wrapper for raw attach/detach
- // TODO: could we remember if we're already attached? idk if it's worth it
- try { await attachDebugger(tabId); }
- catch (e) {
- if (e.message.indexOf('Another debugger is already attached') !== -1) {
- await detachDebugger(tabId);
- await attachDebugger(tabId);
- }
- }
- // TODO: detach automatically? some kind of reference counting thing?
- },
- enableDomainForTab: async function(tabId, domain) {
- // TODO: could we remember if we're already enabled? idk if it's worth it
- await sendDebuggerCommand(tabId, `${domain}.enable`, {});
- }
-};
-function sendDebuggerCommand(tabId, method, commandParams) {
- return new Promise((resolve, reject) =>
- chrome.debugger.sendCommand({tabId}, method, commandParams, result => {
- if (result) { resolve(result); } else { reject(chrome.runtime.lastError); }
- })
- );
-}
-
-const BrowserState = { scriptsForTab: {} };
-(function() {
+const TabManager = (function() {
if (TESTING) return;
-
chrome.debugger.onEvent.addListener((source, method, params) => {
console.log(source, method, params);
if (method === "Page.frameStartedLoading") {
// we're gonna assume we're always plugged into both Page and Debugger.
- BrowserState.scriptsForTab[source.tabId] = [];
+ TabManager.scriptsForTab[source.tabId] = [];
} else if (method === "Debugger.scriptParsed") {
- BrowserState.scriptsForTab[source.tabId] = BrowserState.scriptsForTab[source.tabId] || [];
- BrowserState.scriptsForTab[source.tabId].push(params);
+ TabManager.scriptsForTab[source.tabId] = TabManager.scriptsForTab[source.tabId] || [];
+ TabManager.scriptsForTab[source.tabId].push(params);
}
});
+
+ return {
+ scriptsForTab: {},
+ debugTab: async function(tabId) {
+ // meant to be higher-level wrapper for raw attach/detach
+ // TODO: could we remember if we're already attached? idk if it's worth it
+ try { await attachDebugger(tabId); }
+ catch (e) {
+ if (e.message.indexOf('Another debugger is already attached') !== -1) {
+ await detachDebugger(tabId);
+ await attachDebugger(tabId);
+ }
+ }
+ // TODO: detach automatically? some kind of reference counting thing?
+ },
+ enableDomainForTab: async function(tabId, domain) {
+ // TODO: could we remember if we're already enabled? idk if it's worth it
+ if (domain === 'Debugger') { TabManager.scriptsForTab[tabId] = []; }
+ await sendDebuggerCommand(tabId, `${domain}.enable`, {});
+ }
+ };
})();
+function sendDebuggerCommand(tabId, method, commandParams) {
+ return new Promise((resolve, reject) =>
+ chrome.debugger.sendCommand({tabId}, method, commandParams, result => {
+ if (result) { resolve(result); } else { reject(chrome.runtime.lastError); }
+ })
+ );
+}
const router = {};
@@ -288,14 +288,16 @@ router["/tabs/by-id/*/control"] = {
},
async readdir({path}) {
const tabId = parseInt(pathComponent(path, -3));
- return { entries: [".", "..", ...BrowserState.scriptsForTab[tabId].map(params => sanitize(params.url).slice(0, 200) + "_" + params.scriptId)] };
+ return { entries: [".", "..", ...TabManager.scriptsForTab[tabId].map(params => sanitize(params.url).slice(0, 200) + "_" + params.scriptId)] };
}
};
router["/tabs/by-id/*/debugger/scripts/*"] = defineFile(async path => {
const [tabId, suffix] = [parseInt(pathComponent(path, -4)), pathComponent(path, -1)];
await TabManager.debugTab(tabId);
+ console.log('BEFORE', TabManager.scriptsForTab[tabId].length);
await TabManager.enableDomainForTab(tabId, "Page");
await TabManager.enableDomainForTab(tabId, "Debugger");
+ console.log('AFTER', TabManager.scriptsForTab[tabId].length)
const parts = path.split("_"); const scriptId = parts[parts.length - 1];
const {scriptSource} = await sendDebuggerCommand(tabId, "Debugger.getScriptSource", {scriptId});
diff --git a/tabfs.md b/tabfs.md
index 840c3fe..443395b 100644
--- a/tabfs.md
+++ b/tabfs.md
@@ -358,7 +358,18 @@ TODO: make diagrams?
GPLv3
-## things that would be cool to do
+## things that could/should be done
+
+- add more synthetic files!! view DOM nodes, snapshot current HTML of
+ page, spelunk into living objects. see what your code is doing. make
+ more files writable also
+
+- build more (GUI and CLI) tools on top, on both sides
+
+- more persistence stuff
+
+- why can't Preview open images? GUI programs often struggle with the
+ filesystem for some reason. CLI more reliable
- multithreading. the key constraint is that I pass `-s` to
`fuse_main` in `tabfs.c`, which makes everything
@@ -379,18 +390,20 @@ GPLv3
filesystem, even ones you'd assume are reasonably battle-tested and
well-engineered like sshfs?
+- other performance stuff -- remembering when we're already attached
+ to things, reference counting, minimizing browser roundtrips. not
+ sure impact of these
+
+- TypeScript (how to do with the minimum amount of build system and
+ package manager nonsense?)
+
- look into support for Firefox / Windows / Safari / etc. best FUSE
equiv for Windows? can you bridge to the remote debugging APIs that
all of them already have to get the augmented functionality? or just
implement it all with JS monkey patching?
-- window management. tab management where you can move tabs
-
-- snapshotting (snapshot.html / snapshot.mhtml file)
-
-- fix leaks
-
-- elim unnecessary round-trips / browser API calls
+- window management. tab management where you can move tabs. 'merge
+ all windows'
## hmm
@@ -423,14 +436,30 @@ suggests making an extension is a whole Thing, a whole Project. like,
why can't I just take a minute to ask my browser a question or tell it
to automate something? lightness
-- a lot of existing uses of these APIs are in an automation context,
- if you want to test your code on an automated browser. I'm much more
- interested in an interactive, end-user context. augmenting the way I
- use my normal browser. that's why this is an extension. it doesn't
- require your browser to run in some weird remote debugging mode that
- you'd always forget to turn on. it just [stays
+- a lot of existing uses of these APIs are in an automation context:
+ testing your code on a robotic browser as part of some pipeline. I'm
+ much more interested in an interactive, end-user context. augmenting
+ the way I use my everyday browser. that's why this is an
+ extension. it doesn't require your browser to run in some weird
+ remote debugging mode that you'd always forget to turn on. it just
+ [stays
running](https://twitter.com/rsnous/status/1340150818553561094)
+- system call tracing (dtruss or strace) super useful when anything is
+ going wrong. (need to disable SIP on macOS, though.) the
+ combination of dtruss (application side) & console logging fs
+ request/response (filesystem side) gives a huge amount of insight
+ into basically any problem, end to end
+
+- for a lot of things in the extension API, the browser can notify you
+ of updates but there's no apparent way to query the full current
+ state. so we'd need to sit in a lot of these places from the
+ beginning and accumulate the incoming events to know, like, the last
+ time a tab was updated, or the list of scripts currently running on
+ a tab
+
+- async/await was absolutely vital to making this readable
+
- open input space -- filesystem. (it reminds me of Screenotate.)
- now you have this whole 'language', this whole toolset, to control
diff --git a/test/test.c b/test/test.c
index b4fe5b4..edb1c99 100644
--- a/test/test.c
+++ b/test/test.c
@@ -41,6 +41,9 @@ int main() {
assert(system("echo file://$(pwd)/test-page.html > ../fs/mnt/tabs/create") == 0);
assert(file_contents_equal("../fs/mnt/tabs/last-focused/title.txt", "Title of Test Page"));
assert(file_contents_equal("../fs/mnt/tabs/last-focused/text.txt", "Body Text of Test Page"));
+
+ assert(system("ls ../fs/mnt/tabs/last-focused/debugger/scripts") == 0);
+
assert(system("echo remove > ../fs/mnt/tabs/last-focused/control") == 0);
}