mirror of
https://github.com/osnr/TabFS.git
synced 2024-06-10 09:52:21 +02:00
prevent explosion of scriptsForTab!
This commit is contained in:
parent
44c8dfcec6
commit
705b245be5
|
@ -52,24 +52,41 @@ async function detachDebugger(tabId) {
|
||||||
else { resolve(); }
|
else { resolve(); }
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
const TabManager = {
|
const TabManager = (function() {
|
||||||
debugTab: async function(tabId) {
|
if (TESTING) return;
|
||||||
// meant to be higher-level wrapper for raw attach/detach
|
chrome.debugger.onEvent.addListener((source, method, params) => {
|
||||||
// TODO: could we remember if we're already attached? idk if it's worth it
|
console.log(source, method, params);
|
||||||
try { await attachDebugger(tabId); }
|
if (method === "Page.frameStartedLoading") {
|
||||||
catch (e) {
|
// we're gonna assume we're always plugged into both Page and Debugger.
|
||||||
if (e.message.indexOf('Another debugger is already attached') !== -1) {
|
TabManager.scriptsForTab[source.tabId] = [];
|
||||||
await detachDebugger(tabId);
|
|
||||||
await attachDebugger(tabId);
|
} else if (method === "Debugger.scriptParsed") {
|
||||||
}
|
TabManager.scriptsForTab[source.tabId] = TabManager.scriptsForTab[source.tabId] || [];
|
||||||
|
TabManager.scriptsForTab[source.tabId].push(params);
|
||||||
}
|
}
|
||||||
// TODO: detach automatically? some kind of reference counting thing?
|
});
|
||||||
},
|
|
||||||
enableDomainForTab: async function(tabId, domain) {
|
return {
|
||||||
// TODO: could we remember if we're already enabled? idk if it's worth it
|
scriptsForTab: {},
|
||||||
await sendDebuggerCommand(tabId, `${domain}.enable`, {});
|
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) {
|
function sendDebuggerCommand(tabId, method, commandParams) {
|
||||||
return new Promise((resolve, reject) =>
|
return new Promise((resolve, reject) =>
|
||||||
chrome.debugger.sendCommand({tabId}, method, commandParams, result => {
|
chrome.debugger.sendCommand({tabId}, method, commandParams, result => {
|
||||||
|
@ -78,23 +95,6 @@ function sendDebuggerCommand(tabId, method, commandParams) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const BrowserState = { scriptsForTab: {} };
|
|
||||||
(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] = [];
|
|
||||||
|
|
||||||
} else if (method === "Debugger.scriptParsed") {
|
|
||||||
BrowserState.scriptsForTab[source.tabId] = BrowserState.scriptsForTab[source.tabId] || [];
|
|
||||||
BrowserState.scriptsForTab[source.tabId].push(params);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})();
|
|
||||||
|
|
||||||
const router = {};
|
const router = {};
|
||||||
|
|
||||||
const Cache = {
|
const Cache = {
|
||||||
|
@ -288,14 +288,16 @@ router["/tabs/by-id/*/control"] = {
|
||||||
},
|
},
|
||||||
async readdir({path}) {
|
async readdir({path}) {
|
||||||
const tabId = parseInt(pathComponent(path, -3));
|
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 => {
|
router["/tabs/by-id/*/debugger/scripts/*"] = defineFile(async path => {
|
||||||
const [tabId, suffix] = [parseInt(pathComponent(path, -4)), pathComponent(path, -1)];
|
const [tabId, suffix] = [parseInt(pathComponent(path, -4)), pathComponent(path, -1)];
|
||||||
await TabManager.debugTab(tabId);
|
await TabManager.debugTab(tabId);
|
||||||
|
console.log('BEFORE', TabManager.scriptsForTab[tabId].length);
|
||||||
await TabManager.enableDomainForTab(tabId, "Page");
|
await TabManager.enableDomainForTab(tabId, "Page");
|
||||||
await TabManager.enableDomainForTab(tabId, "Debugger");
|
await TabManager.enableDomainForTab(tabId, "Debugger");
|
||||||
|
console.log('AFTER', TabManager.scriptsForTab[tabId].length)
|
||||||
|
|
||||||
const parts = path.split("_"); const scriptId = parts[parts.length - 1];
|
const parts = path.split("_"); const scriptId = parts[parts.length - 1];
|
||||||
const {scriptSource} = await sendDebuggerCommand(tabId, "Debugger.getScriptSource", {scriptId});
|
const {scriptSource} = await sendDebuggerCommand(tabId, "Debugger.getScriptSource", {scriptId});
|
||||||
|
|
57
tabfs.md
57
tabfs.md
|
@ -358,7 +358,18 @@ TODO: make diagrams?
|
||||||
|
|
||||||
GPLv3
|
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
|
- multithreading. the key constraint is that I pass `-s` to
|
||||||
`fuse_main` in `tabfs.c`, which makes everything
|
`fuse_main` in `tabfs.c`, which makes everything
|
||||||
|
@ -379,18 +390,20 @@ GPLv3
|
||||||
filesystem, even ones you'd assume are reasonably battle-tested and
|
filesystem, even ones you'd assume are reasonably battle-tested and
|
||||||
well-engineered like sshfs?
|
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
|
- look into support for Firefox / Windows / Safari / etc. best FUSE
|
||||||
equiv for Windows? can you bridge to the remote debugging APIs that
|
equiv for Windows? can you bridge to the remote debugging APIs that
|
||||||
all of them already have to get the augmented functionality? or just
|
all of them already have to get the augmented functionality? or just
|
||||||
implement it all with JS monkey patching?
|
implement it all with JS monkey patching?
|
||||||
|
|
||||||
- window management. tab management where you can move tabs
|
- window management. tab management where you can move tabs. 'merge
|
||||||
|
all windows'
|
||||||
- snapshotting (snapshot.html / snapshot.mhtml file)
|
|
||||||
|
|
||||||
- fix leaks
|
|
||||||
|
|
||||||
- elim unnecessary round-trips / browser API calls
|
|
||||||
|
|
||||||
## hmm
|
## 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
|
why can't I just take a minute to ask my browser a question or tell it
|
||||||
to automate something? lightness
|
to automate something? lightness
|
||||||
|
|
||||||
- a lot of existing uses of these APIs are in an automation context,
|
- 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
|
testing your code on a robotic browser as part of some pipeline. I'm
|
||||||
interested in an interactive, end-user context. augmenting the way I
|
much more interested in an interactive, end-user context. augmenting
|
||||||
use my normal browser. that's why this is an extension. it doesn't
|
the way I use my everyday browser. that's why this is an
|
||||||
require your browser to run in some weird remote debugging mode that
|
extension. it doesn't require your browser to run in some weird
|
||||||
you'd always forget to turn on. it just [stays
|
remote debugging mode that you'd always forget to turn on. it just
|
||||||
|
[stays
|
||||||
running](https://twitter.com/rsnous/status/1340150818553561094)
|
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.)
|
- open input space -- filesystem. (it reminds me of Screenotate.)
|
||||||
|
|
||||||
- now you have this whole 'language', this whole toolset, to control
|
- now you have this whole 'language', this whole toolset, to control
|
||||||
|
|
|
@ -41,6 +41,9 @@ int main() {
|
||||||
assert(system("echo file://$(pwd)/test-page.html > ../fs/mnt/tabs/create") == 0);
|
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/title.txt", "Title of Test Page"));
|
||||||
assert(file_contents_equal("../fs/mnt/tabs/last-focused/text.txt", "Body Text 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);
|
assert(system("echo remove > ../fs/mnt/tabs/last-focused/control") == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue