mirror of
https://github.com/osnr/TabFS.git
synced 2024-05-21 23:16:39 +02:00
cleanup refcount stuff that wasn't being used anyway, update md
This commit is contained in:
parent
e31f915bdd
commit
b8181bd6f5
0
.gitmodules
vendored
0
.gitmodules
vendored
|
@ -53,35 +53,21 @@ async function detachDebugger(tabId) {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
const TabManager = {
|
const TabManager = {
|
||||||
tabState: {},
|
|
||||||
|
|
||||||
// higher-level wrapper which avoids unnecessary attaches and tries
|
|
||||||
// to keep debugger attached in a reasonable state whenever you call
|
|
||||||
// it (do we need this?)
|
|
||||||
debugTab: async function(tabId) {
|
debugTab: async function(tabId) {
|
||||||
this.tabState[tabId] = this.tabState[tabId] || {};
|
// meant to be higher-level wrapper for raw attach/detach
|
||||||
if (this.tabState[tabId].debugging) {
|
// TODO: could we remember if we're already attached? idk if it's worth it
|
||||||
this.tabState[tabId].debugging += 1;
|
try { await attachDebugger(tabId); }
|
||||||
|
catch (e) {
|
||||||
} else {
|
if (e.message.indexOf('Another debugger is already attached') !== -1) {
|
||||||
try { await attachDebugger(tabId); }
|
await detachDebugger(tabId);
|
||||||
catch (e) {
|
await attachDebugger(tabId);
|
||||||
if (e.message.indexOf('Another debugger is already attached') !== -1) {
|
|
||||||
await detachDebugger(tabId);
|
|
||||||
await attachDebugger(tabId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.tabState[tabId].debugging = 1;
|
|
||||||
}
|
}
|
||||||
// FIXME: unsubscribe
|
// TODO: detach automatically? some kind of reference counting thing?
|
||||||
},
|
},
|
||||||
enableDomainForTab: async function(tabId, domain) {
|
enableDomainForTab: async function(tabId, domain) {
|
||||||
this.tabState[tabId] = this.tabState[tabId] || {};
|
// TODO: could we remember if we're already enabled? idk if it's worth it
|
||||||
if (this.tabState[tabId][domain]) { this.tabState[tabId][domain] += 1;
|
await sendDebuggerCommand(tabId, `${domain}.enable`, {});
|
||||||
} else {
|
|
||||||
await sendDebuggerCommand(tabId, `${domain}.enable`, {});
|
|
||||||
this.tabState[tabId][domain] = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
function sendDebuggerCommand(tabId, method, commandParams) {
|
function sendDebuggerCommand(tabId, method, commandParams) {
|
||||||
|
@ -217,7 +203,6 @@ router["/tabs/by-id"] = {
|
||||||
// TODO: dom/ ?
|
// TODO: dom/ ?
|
||||||
// TODO: globals/ ?
|
// TODO: globals/ ?
|
||||||
|
|
||||||
// screenshot.png (FIXME: how to keep from blocking when unfocused?)
|
|
||||||
// TODO: archive.mhtml ?
|
// TODO: archive.mhtml ?
|
||||||
// TODO: printed.pdf
|
// TODO: printed.pdf
|
||||||
// control
|
// control
|
||||||
|
@ -373,6 +358,9 @@ router["/windows/last-focused"] = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
router["/windows/*/visible-tab.png"] = { ...defineFile(async path => {
|
router["/windows/*/visible-tab.png"] = { ...defineFile(async path => {
|
||||||
|
// this is a window thing (rn, the _only_ window thing) because you
|
||||||
|
// can only capture the visible tab for each window anyway; you
|
||||||
|
// can't take a screenshot of just any arbitrary tab
|
||||||
const windowId = parseInt(pathComponent(path, -2));
|
const windowId = parseInt(pathComponent(path, -2));
|
||||||
const dataUrl = await browser.tabs.captureVisibleTab(windowId, {format: 'png'});
|
const dataUrl = await browser.tabs.captureVisibleTab(windowId, {format: 'png'});
|
||||||
return Uint8Array.from(atob(dataUrl.substr(("data:image/png;base64,").length)),
|
return Uint8Array.from(atob(dataUrl.substr(("data:image/png;base64,").length)),
|
||||||
|
|
116
tabfs.md
116
tabfs.md
|
@ -4,7 +4,7 @@ title: TabFS
|
||||||
<!-- I'm setting this page in Verdana-on-gray so I feel more comfortable -->
|
<!-- I'm setting this page in Verdana-on-gray so I feel more comfortable -->
|
||||||
<!-- jotting random notes and stuff down. -->
|
<!-- jotting random notes and stuff down. -->
|
||||||
<style>
|
<style>
|
||||||
body { font-family: Verdana; background: #eee; }
|
body { font-family: Verdana, sans-serif; background: #eee; }
|
||||||
h1 { font-family: Helvetica; }
|
h1 { font-family: Helvetica; }
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
@ -29,14 +29,22 @@ Firefox, on macOS and Linux.[^otherbrowsers]
|
||||||
Each of your open tabs is mapped to a folder.
|
Each of your open tabs is mapped to a folder.
|
||||||
|
|
||||||
<div class="figure">
|
<div class="figure">
|
||||||
<img src="doc/finder.png">
|
<img src="doc/00-browser.png" style="width: 70%">
|
||||||
|
<img src="doc/00-finder.png" style="width: 80%; max-height: 1000px">
|
||||||
|
<p class="caption" style="margin-top: -20px">I have 3 tabs open, and
|
||||||
|
they map to 3 folders in TabFS</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
The files inside a tab's folder directly reflect (and can control) the
|
The files inside a tab's folder directly reflect (and can control) the
|
||||||
state of that tab in your browser. (TODO: update as I add more)
|
state of that tab in your browser. (TODO: update as I add more)
|
||||||
|
|
||||||
<div class="figure">
|
<div class="figure">
|
||||||
<img src="doc/finder-contents.png">
|
<video autoplay loop muted>
|
||||||
|
<source src="doc/finder-contents.mp4" type="video/mp4">
|
||||||
|
</video>
|
||||||
|
<p class="caption">Example: the url.txt, text.txt, and title.txt
|
||||||
|
files inside a tab's folder, which tell me those live properties
|
||||||
|
for that tab</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
This gives you a _ton_ of power, because now you can apply [all the
|
This gives you a _ton_ of power, because now you can apply [all the
|
||||||
|
@ -54,13 +62,17 @@ file](https://twitter.com/rsnous/status/1308588645872435202) that you
|
||||||
can run whenever, and it's no different from scripting any other part
|
can run whenever, and it's no different from scripting any other part
|
||||||
of your computer.
|
of your computer.
|
||||||
|
|
||||||
## Examples of stuff you can do!
|
## Examples of stuff you can do![^examples]
|
||||||
|
|
||||||
|
[^examples]: maybe some of these feel a little more vital and
|
||||||
|
fleshed-out and urgent than others. the things I actually wanted
|
||||||
|
to do and reached for vs. the things that satisfy some pedagogical
|
||||||
|
property (simple to explain, stack on top of the previous example,
|
||||||
|
...)
|
||||||
|
|
||||||
(assuming your current directory is the `fs` subdirectory of the git
|
(assuming your current directory is the `fs` subdirectory of the git
|
||||||
repo and you have the extension running)
|
repo and you have the extension running)
|
||||||
|
|
||||||
(TODO: more of these)
|
|
||||||
|
|
||||||
### List the titles of all the tabs you have open
|
### List the titles of all the tabs you have open
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -74,6 +86,18 @@ Home / Twitter
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Cull tabs like any other files
|
||||||
|
|
||||||
|
<div class="figure">
|
||||||
|
<video autoplay loop muted>
|
||||||
|
<source src="doc/delete.mp4" type="video/mp4">
|
||||||
|
</video>
|
||||||
|
<p class="caption">Selecting and deleting a bunch of tabs in my file manager</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
I'm using Dired in Emacs here, but you could use whatever tools you
|
||||||
|
already feel comfortable managing your files with.
|
||||||
|
|
||||||
### Close all Stack Overflow tabs
|
### Close all Stack Overflow tabs
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -130,15 +154,16 @@ post](https://stackoverflow.com/questions/2963260/how-do-i-auto-reload-a-chrome-
|
||||||
with ways to automate this, but they're all sort of hacky. You need
|
with ways to automate this, but they're all sort of hacky. You need
|
||||||
yet another extension, or you need to tack weird permissions onto your
|
yet another extension, or you need to tack weird permissions onto your
|
||||||
work-in-progress extension, and you don't just get a command you can
|
work-in-progress extension, and you don't just get a command you can
|
||||||
trigger from your editor or shell.
|
trigger from your editor or shell to refresh the extension.
|
||||||
|
|
||||||
TabFS lets you do all this in [an ordinary shell
|
TabFS lets you do all this in [an ordinary shell
|
||||||
script](https://github.com/osnr/playgroundize-devtools-protocol/blob/main/go.sh).
|
script](https://github.com/osnr/playgroundize-devtools-protocol/blob/main/go.sh).
|
||||||
You don't have to write any browser-side code at all.
|
You don't have to write any browser-side code at all.
|
||||||
|
|
||||||
The script linked above turns the extension (this one's title is
|
This script turns an extension (this one's title is "Playgroundize
|
||||||
"Playgroundize DevTools Protocol") off, then turns it back on, then
|
DevTools Protocol") off, then turns it back on, then reloads any tabs
|
||||||
reloads any Chrome DevTools pages that are open:
|
that have the relevant pages open (in this case, I decided it's tabs
|
||||||
|
whose titles start with "Chrome Dev"):
|
||||||
|
|
||||||
```
|
```
|
||||||
#!/bin/bash -eux
|
#!/bin/bash -eux
|
||||||
|
@ -147,12 +172,8 @@ echo true > mnt/extensions/Playg*/enabled
|
||||||
echo reload | tee mnt/tabs/by-title/Chrome_Dev*/control
|
echo reload | tee mnt/tabs/by-title/Chrome_Dev*/control
|
||||||
```
|
```
|
||||||
|
|
||||||
I mapped this script to Ctrl-. in my Emacs, so now I can just hit that
|
I mapped this script to Ctrl-. in my text editor, and now I just hit
|
||||||
every time I want to reload my extension code!
|
that every time I want to reload my extension code.
|
||||||
|
|
||||||
### TODO: Cull tabs like any other files
|
|
||||||
|
|
||||||
I do this in Emacs dired.
|
|
||||||
|
|
||||||
### TODO: Live edit a running Web page
|
### TODO: Live edit a running Web page
|
||||||
|
|
||||||
|
@ -263,10 +284,13 @@ click "Inspect")
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
This console is also incredibly helpful for debugging anything that
|
This console is also incredibly helpful for debugging anything that
|
||||||
goes wrong, which probably will happen.
|
goes wrong, which probably will happen. (If you get a generic I/O
|
||||||
|
error at the shell when running a command on TabFS, that probably
|
||||||
|
means that an exception happened which you can check here.)
|
||||||
|
|
||||||
(My OS and applications are pretty chatty! They do a lot of
|
(My OS and applications are pretty chatty. They do a lot of
|
||||||
operations, even when I don't feel like I'm actually doing anything.)
|
operations, even when I don't feel like I'm actually doing
|
||||||
|
anything. My sense is that macOS is generally chattier than Linux.)
|
||||||
|
|
||||||
## Design
|
## Design
|
||||||
|
|
||||||
|
@ -280,10 +304,17 @@ operations, even when I don't feel like I'm actually doing anything.)
|
||||||
**The most interesting file**. Defines all the synthetic files and
|
**The most interesting file**. Defines all the synthetic files and
|
||||||
what browser operations they invoke behind the scenes.[^frustrates]
|
what browser operations they invoke behind the scenes.[^frustrates]
|
||||||
|
|
||||||
[^frustrates]: it frustrates me that I can't have something like a
|
[^frustrates]: it frustrates me that I can't show you, like, a table
|
||||||
table of contents for this source file. because it does have a
|
of contents for this source file. because it does have a structure
|
||||||
structure to it! so I feel like the UI for looking at the file
|
to it! so I feel like the UI for looking at this one file should
|
||||||
should highlight and exploit that structure.
|
be
|
||||||
|
[custom-tailored](https://twitter.com/rsnous/status/1262956983222591488)
|
||||||
|
to
|
||||||
|
[highlight](https://twitter.com/rsnous/status/1262957486262214657)
|
||||||
|
and exploit that structure. (I wonder what other cases like this
|
||||||
|
are out there, where ad hoc UI for one file would be useful. like
|
||||||
|
if you have tangled-but-regular business logic, or the giant
|
||||||
|
opcode switch statement of an emulator or interpreter.)
|
||||||
|
|
||||||
I want to link you to a particular route and talk about it here
|
I want to link you to a particular route and talk about it here
|
||||||
and also have some kind of
|
and also have some kind of
|
||||||
|
@ -327,14 +358,14 @@ TODO: make diagrams?
|
||||||
|
|
||||||
GPLv3
|
GPLv3
|
||||||
|
|
||||||
## things that would be good to do
|
## things that would be cool to do
|
||||||
|
|
||||||
- multithreading. the key constraint is that I give `-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
|
||||||
single-threaded. but I'm not clear on how much it would improve
|
single-threaded. but I'm not clear on how much it would improve
|
||||||
performance? maybe a lot, but not sure. maybe workload-dependent?
|
performance? maybe a lot, but not sure. maybe workload-dependent?
|
||||||
|
|
||||||
the extension itself (and the standard I/O comm between the fs and
|
the extension itself (and the stdin/stdout comm between the fs and
|
||||||
the extension) would still be single-threaded, but you could
|
the extension) would still be single-threaded, but you could
|
||||||
interleave requests since most of that stuff is async. like the
|
interleave requests since most of that stuff is async. like the
|
||||||
screenshot request that takes like half a second, you could do other
|
screenshot request that takes like half a second, you could do other
|
||||||
|
@ -344,15 +375,19 @@ GPLv3
|
||||||
individual request hangs anyway; they're not expecting the
|
individual request hangs anyway; they're not expecting the
|
||||||
filesystem to be so slow (and to be fair to them, they really have
|
filesystem to be so slow (and to be fair to them, they really have
|
||||||
[no way](https://twitter.com/whitequark/status/1133905587819941888)
|
[no way](https://twitter.com/whitequark/status/1133905587819941888)
|
||||||
to). some of these are problems that may be inevitable for any FUSE
|
to). some of these problems may be inevitable for any FUSE
|
||||||
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?
|
||||||
|
|
||||||
- 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 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
|
||||||
|
|
||||||
|
- snapshotting (snapshot.html / snapshot.mhtml file)
|
||||||
|
|
||||||
- fix leaks
|
- fix leaks
|
||||||
|
|
||||||
- elim unnecessary round-trips / browser API calls
|
- elim unnecessary round-trips / browser API calls
|
||||||
|
@ -376,9 +411,10 @@ inside of the browser. can we have 'browser tabs as files'?
|
||||||
|
|
||||||
- there are two 'operating systems' on my computer, the browser and
|
- there are two 'operating systems' on my computer, the browser and
|
||||||
Unix, and Unix is by far the more accessible and programmable and
|
Unix, and Unix is by far the more accessible and programmable and
|
||||||
cohesive as a computing environment (shells, processes), even though
|
cohesive as a computing environment (it has concepts that compose!
|
||||||
it's arguably the less important to my daily life. how can the browser
|
shell, processes, files), even though it's arguably the less important
|
||||||
take on these properties?
|
to my daily life. how can the browser take on more of the properties
|
||||||
|
of Unix?
|
||||||
|
|
||||||
- it's [way too
|
- it's [way too
|
||||||
hard](https://twitter.com/rsnous/status/1342236988938719232) to make a
|
hard](https://twitter.com/rsnous/status/1342236988938719232) to make a
|
||||||
|
@ -387,6 +423,14 @@ 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,
|
||||||
|
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
|
||||||
|
running](https://twitter.com/rsnous/status/1340150818553561094)
|
||||||
|
|
||||||
- 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
|
||||||
|
@ -410,11 +454,13 @@ files
|
||||||
- fake filesystems talk
|
- fake filesystems talk
|
||||||
|
|
||||||
- [rmdir a non-empty
|
- [rmdir a non-empty
|
||||||
directory](https://twitter.com/rsnous/status/1107427906832089088). I
|
directory](https://twitter.com/rsnous/status/1107427906832089088)
|
||||||
feel like a new OS, something like Plan 9, should
|
-- when I was thinking if you should be able to `rm by-id/TABID`
|
||||||
|
even though `TABID` is a folder. I feel like a new OS, something
|
||||||
|
like Plan 9, should
|
||||||
[generalize](https://twitter.com/rsnous/status/1070830656005988352)
|
[generalize](https://twitter.com/rsnous/status/1070830656005988352)
|
||||||
its file I/O APIs just enough to avoid problems like this. like
|
its file I/O APIs just enough to avoid problems like this. like
|
||||||
design them with the disk in mind but also a few concrete cases
|
design them with the disk in mind but also a few concrete cases of
|
||||||
of synthetic filesystems, very slow remote filesystems, etc
|
synthetic filesystems, very slow remote filesystems, etc
|
||||||
|
|
||||||
do you like setting up sockets? I don't
|
do you like setting up sockets? I don't
|
||||||
|
|
Loading…
Reference in a new issue