mirror of
https://github.com/osnr/TabFS.git
synced 2024-05-21 15:06:47 +02:00
start on refactor to eliminate layer of fs op handling
This commit is contained in:
parent
a7e38dc258
commit
976c5ef20a
|
@ -173,7 +173,7 @@ GPLv3
|
||||||
## hmm
|
## hmm
|
||||||
|
|
||||||
it's way too hard to make an extension. even 'make an extension' is
|
it's way too hard to make an extension. even 'make an extension' is
|
||||||
a bad framing
|
a bad framing. lightness
|
||||||
|
|
||||||
open input space -- filesystem
|
open input space -- filesystem
|
||||||
|
|
||||||
|
@ -191,3 +191,4 @@ processes as files. the real process is the browser.
|
||||||
browser and Unix
|
browser and Unix
|
||||||
|
|
||||||
rmdir a non-empty directory
|
rmdir a non-empty directory
|
||||||
|
|
||||||
|
|
|
@ -89,9 +89,17 @@ browser.windows.onFocusChanged.addListener(windowId => {
|
||||||
view of what the whole filesystem looks like at a glance. */
|
view of what the whole filesystem looks like at a glance. */
|
||||||
const router = {};
|
const router = {};
|
||||||
|
|
||||||
|
const directoryGetattr = async function() {
|
||||||
|
return {
|
||||||
|
st_mode: unix.S_IFDIR | 0755,
|
||||||
|
st_nlink: 3,
|
||||||
|
st_size: 0,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
function withTab(handler) {
|
function withTab(handler) {
|
||||||
return {
|
return {
|
||||||
async getattr(path) {
|
async getattr({path}) {
|
||||||
const tab = await browser.tabs.get(parseInt(pathComponent(path, -2)));
|
const tab = await browser.tabs.get(parseInt(pathComponent(path, -2)));
|
||||||
return {
|
return {
|
||||||
st_mode: unix.S_IFREG | 0444,
|
st_mode: unix.S_IFREG | 0444,
|
||||||
|
@ -99,15 +107,15 @@ function withTab(handler) {
|
||||||
st_size: stringSize(handler(tab))
|
st_size: stringSize(handler(tab))
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
async read(path, fh, size, offset) {
|
async read({path, fh, size, offset}) {
|
||||||
const tab = await browser.tabs.get(parseInt(pathComponent(path, -2)));
|
const tab = await browser.tabs.get(parseInt(pathComponent(path, -2)));
|
||||||
return handler(tab).substr(offset, size);
|
return { buf: handler(tab).substr(offset, size) };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
function fromScript(code) {
|
function fromScript(code) {
|
||||||
return {
|
return {
|
||||||
async getattr(path) {
|
async getattr({path}) {
|
||||||
const tabId = parseInt(pathComponent(path, -2));
|
const tabId = parseInt(pathComponent(path, -2));
|
||||||
return {
|
return {
|
||||||
st_mode: unix.S_IFREG | 0444,
|
st_mode: unix.S_IFREG | 0444,
|
||||||
|
@ -115,33 +123,35 @@ function fromScript(code) {
|
||||||
st_size: stringSize((await browser.tabs.executeScript(tabId, {code}))[0])
|
st_size: stringSize((await browser.tabs.executeScript(tabId, {code}))[0])
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
async read(path, fh, size, offset) {
|
async read({path, fh, size, offset}) {
|
||||||
const tabId = parseInt(pathComponent(path, -2));
|
const tabId = parseInt(pathComponent(path, -2));
|
||||||
return (await browser.tabs.executeScript(tabId, {code}))[0]
|
return { buf: (await browser.tabs.executeScript(tabId, {code}))[0]
|
||||||
.substr(offset, size);
|
.substr(offset, size) }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
router["/tabs/by-id"] = {
|
router["/tabs/by-id"] = {
|
||||||
async entries() {
|
getattr: directoryGetattr,
|
||||||
|
async readdir() {
|
||||||
const tabs = await browser.tabs.query({});
|
const tabs = await browser.tabs.query({});
|
||||||
return tabs.map(tab => String(tab.id));
|
return { entries: tabs.map(tab => String(tab.id)) };
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
router["/tabs/by-id/*/url"] = withTab(tab => tab.url + "\n");
|
router["/tabs/by-id/*/url"] = withTab(tab => tab.url + "\n");
|
||||||
router["/tabs/by-id/*/title"] = withTab(tab => tab.title + "\n");
|
router["/tabs/by-id/*/title"] = withTab(tab => tab.title + "\n");
|
||||||
router["/tabs/by-id/*/text"] = fromScript(`document.body.innerText`);
|
router["/tabs/by-id/*/text"] = fromScript(`document.body.innerText`);
|
||||||
router["/tabs/by-id/*/resources"] = {
|
router["/tabs/by-id/*/resources"] = {
|
||||||
async opendir(path) {
|
getattr: directoryGetattr,
|
||||||
|
async opendir({path}) {
|
||||||
const tabId = parseInt(pathComponent(path, -2));
|
const tabId = parseInt(pathComponent(path, -2));
|
||||||
await debugTab(tabId);
|
await debugTab(tabId);
|
||||||
return 0;
|
return 0;
|
||||||
},
|
},
|
||||||
async entries(path) {
|
async readdir({path}) {
|
||||||
const tabId = parseInt(pathComponent(path, -2));
|
const tabId = parseInt(pathComponent(path, -2));
|
||||||
const {frameTree} = await sendDebuggerCommand(tabId, "Page.getResourceTree", {});
|
const {frameTree} = await sendDebuggerCommand(tabId, "Page.getResourceTree", {});
|
||||||
return frameTree.resources.map(r => sanitize(String(r.url).slice(0, 200)));
|
return { entries: frameTree.resources.map(r => sanitize(String(r.url).slice(0, 200))) };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
router["/tabs/by-id/*/resources/*"] = {
|
router["/tabs/by-id/*/resources/*"] = {
|
||||||
|
@ -171,6 +181,9 @@ router["/tabs/by-id/*/resources/*"] = {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
async open(path) {
|
||||||
|
|
||||||
},
|
},
|
||||||
async read(path, fh, size, offset) {
|
async read(path, fh, size, offset) {
|
||||||
const tabId = parseInt(pathComponent(path, -3));
|
const tabId = parseInt(pathComponent(path, -3));
|
||||||
|
@ -203,8 +216,15 @@ router["/tabs/by-id/*/resources/*"] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
router["/tabs/by-id/*/control"] = {
|
router["/tabs/by-id/*/control"] = {
|
||||||
|
async getattr() { // generic read-only file attr
|
||||||
|
return {
|
||||||
|
st_mode: unix.S_IFREG | 0222,
|
||||||
|
st_nlink: 1,
|
||||||
|
st_size: 100 // FIXME
|
||||||
|
};
|
||||||
|
},
|
||||||
// echo remove >> mnt/tabs/by-id/1644/control
|
// echo remove >> mnt/tabs/by-id/1644/control
|
||||||
async write(path, buf) {
|
async write({path, buf}) {
|
||||||
const tabId = parseInt(pathComponent(path, -2));
|
const tabId = parseInt(pathComponent(path, -2));
|
||||||
const command = buf.trim();
|
const command = buf.trim();
|
||||||
// can use `discard`, `remove`, `reload`, `goForward`, `goBack`...
|
// can use `discard`, `remove`, `reload`, `goForward`, `goBack`...
|
||||||
|
@ -214,14 +234,15 @@ router["/tabs/by-id/*/control"] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
router["/tabs/by-title"] = {
|
router["/tabs/by-title"] = {
|
||||||
async entries() {
|
getattr: directoryGetattr,
|
||||||
|
async readdir() {
|
||||||
const tabs = await browser.tabs.query({});
|
const tabs = await browser.tabs.query({});
|
||||||
return tabs.map(tab => sanitize(String(tab.title).slice(0, 200)) + "_" + String(tab.id));
|
return { entries: tabs.map(tab => sanitize(String(tab.title).slice(0, 200)) + "_" + String(tab.id)) };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
router["/tabs/by-title/*"] = {
|
router["/tabs/by-title/*"] = {
|
||||||
// a symbolic link to /tabs/by-id/[id for this tab]
|
// a symbolic link to /tabs/by-id/[id for this tab]
|
||||||
async getattr(path) {
|
async getattr({path}) {
|
||||||
const st_size = (await this.readlink(path)).length + 1;
|
const st_size = (await this.readlink(path)).length + 1;
|
||||||
return {
|
return {
|
||||||
st_mode: unix.S_IFLNK | 0444,
|
st_mode: unix.S_IFLNK | 0444,
|
||||||
|
@ -230,16 +251,16 @@ router["/tabs/by-title/*"] = {
|
||||||
st_size
|
st_size
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
async readlink(path) {
|
async readlink({path}) {
|
||||||
const parts = path.split("_");
|
const parts = path.split("_");
|
||||||
const id = parts[parts.length - 1];
|
const id = parts[parts.length - 1];
|
||||||
return "../by-id/" + id;
|
return { buf: "../by-id/" + id };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
router["/tabs/last-focused"] = {
|
router["/tabs/last-focused"] = {
|
||||||
// a symbolic link to /tabs/by-id/[id for this tab]
|
// a symbolic link to /tabs/by-id/[id for this tab]
|
||||||
async getattr(path) {
|
async getattr({path}) {
|
||||||
const st_size = (await this.readlink(path)).length + 1;
|
const st_size = (await this.readlink(path)).length + 1;
|
||||||
return {
|
return {
|
||||||
st_mode: unix.S_IFLNK | 0444,
|
st_mode: unix.S_IFLNK | 0444,
|
||||||
|
@ -248,9 +269,9 @@ router["/tabs/last-focused"] = {
|
||||||
st_size
|
st_size
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
async readlink(path) {
|
async readlink({path}) {
|
||||||
const id = (await browser.tabs.query({ active: true, windowId: lastFocusedWindowId }))[0].id;
|
const id = (await browser.tabs.query({ active: true, windowId: lastFocusedWindowId }))[0].id;
|
||||||
return "by-id/" + id;
|
return { buf: "by-id/" + id };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,18 +295,19 @@ for (let key in router) {
|
||||||
.map(k => k.substr((path === '/' ? 0 : path.length) + 1).split('/')[0]);
|
.map(k => k.substr((path === '/' ? 0 : path.length) + 1).split('/')[0]);
|
||||||
children = [...new Set(children)];
|
children = [...new Set(children)];
|
||||||
|
|
||||||
router[path] = {entries() {
|
router[path] = {
|
||||||
return children;
|
getattr: directoryGetattr,
|
||||||
}}
|
readdir() { return { entries: children }; }
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (TESTING) { // I wish I could color this section with... a pink background, or something.
|
if (TESTING) { // I wish I could color this section with... a pink background, or something.
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
(async () => {
|
(async () => {
|
||||||
assert.deepEqual(await router['/tabs/by-id/*'].entries(), ['url', 'title', 'text', 'control']);
|
assert.deepEqual(await router['/tabs/by-id/*'].readdir(), ['url', 'title', 'text', 'control']);
|
||||||
assert.deepEqual(await router['/'].entries(), ['tabs']);
|
assert.deepEqual(await router['/'].readdir(), ['tabs']);
|
||||||
assert.deepEqual(await router['/tabs'].entries(), ['by-id', 'by-title']);
|
assert.deepEqual(await router['/tabs'].readdir(), ['by-id', 'by-title']);
|
||||||
|
|
||||||
assert.deepEqual(findRoute('/tabs/by-id/TABID/url'), router['/tabs/by-id/*/url']);
|
assert.deepEqual(findRoute('/tabs/by-id/TABID/url'), router['/tabs/by-id/*/url']);
|
||||||
})()
|
})()
|
||||||
|
@ -314,88 +336,89 @@ function findRoute(path) {
|
||||||
return router[routingPath];
|
return router[routingPath];
|
||||||
}
|
}
|
||||||
|
|
||||||
const ops = {
|
/* const ops = {
|
||||||
async getattr({path}) {
|
* async getattr({path}) {
|
||||||
let route = findRoute(path);
|
* let route = findRoute(path);
|
||||||
if (route.getattr) {
|
* if (route.getattr) {
|
||||||
return {
|
* return {
|
||||||
st_mode: 0,
|
* st_mode: 0,
|
||||||
st_nlink: 0,
|
* st_nlink: 0,
|
||||||
st_size: 0,
|
* st_size: 0,
|
||||||
...(await route.getattr(path))
|
* ...(await route.getattr(path))
|
||||||
};
|
* };
|
||||||
} else if (route.read || route.write) {
|
* } else if (route.read || route.write) {
|
||||||
// default file attrs
|
* // default file attrs
|
||||||
return {
|
* return {
|
||||||
st_mode: unix.S_IFREG | ((route.read && 0444) || (route.write && 0222)),
|
* st_mode: unix.S_IFREG | ((route.read && 0444) || (route.write && 0222)),
|
||||||
st_nlink: 1,
|
* st_nlink: 1,
|
||||||
st_size: 100 // FIXME
|
* st_size: 100 // FIXME
|
||||||
};
|
* };
|
||||||
} else {
|
* } else {
|
||||||
// default dir attrs
|
* // default dir attrs
|
||||||
return {
|
* return {
|
||||||
st_mode: unix.S_IFDIR | 0755,
|
* st_mode: unix.S_IFDIR | 0755,
|
||||||
st_nlink: 3,
|
* st_nlink: 3,
|
||||||
st_size: 0
|
* st_size: 0
|
||||||
};
|
* };
|
||||||
}
|
* }
|
||||||
},
|
* },
|
||||||
|
*
|
||||||
async open({path}) {
|
* async open({path}) {
|
||||||
let route = findRoute(path);
|
* let route = findRoute(path);
|
||||||
if (route.open) return { fh: await route.open(path) };
|
* if (route.open) return { fh: await route.open(path) };
|
||||||
else return { fh: 0 }; // empty fh
|
* else return { fh: 0 }; // empty fh
|
||||||
},
|
* },
|
||||||
|
*
|
||||||
async read({path, fh, size, offset}) {
|
* async read({path, fh, size, offset}) {
|
||||||
let route = findRoute(path);
|
* let route = findRoute(path);
|
||||||
if (route.read) {
|
* if (route.read) {
|
||||||
const ret = await route.read(path, fh, size, offset);
|
* const ret = await route.read(path, fh, size, offset);
|
||||||
if (typeof ret === 'string') {
|
* if (typeof ret === 'string') {
|
||||||
return { buf: ret };
|
* return { buf: ret };
|
||||||
} else {
|
* } else {
|
||||||
return ret;
|
* return ret;
|
||||||
}
|
* }
|
||||||
}
|
* }
|
||||||
},
|
* },
|
||||||
async write({path, buf, offset}) {
|
* async write({path, buf, offset}) {
|
||||||
let route = findRoute(path);
|
* let route = findRoute(path);
|
||||||
if (route.write) return route.write(path, atob(buf), offset);
|
* if (route.write) return route.write(path, atob(buf), offset);
|
||||||
},
|
* },
|
||||||
async release({path, fh}) {
|
* async release({path, fh}) {
|
||||||
let route = findRoute(path);
|
* let route = findRoute(path);
|
||||||
if (route.release) return route.release(path, fh);
|
* if (route.release) return route.release(path, fh);
|
||||||
},
|
* },
|
||||||
|
*
|
||||||
async readlink({path}) {
|
* async readlink({path}) {
|
||||||
let route = findRoute(path);
|
* let route = findRoute(path);
|
||||||
if (route.readlink) return { buf: await route.readlink(path) };
|
* if (route.readlink) return { buf: await route.readlink(path) };
|
||||||
},
|
* },
|
||||||
|
*
|
||||||
async opendir({path}) {
|
* async opendir({path}) {
|
||||||
let route = findRoute(path);
|
* let route = findRoute(path);
|
||||||
if (route.opendir) return { fh: await route.opendir(path) };
|
* if (route.opendir) return { fh: await route.opendir(path) };
|
||||||
else return { fh: 0 }; // empty fh
|
* else return { fh: 0 }; // empty fh
|
||||||
},
|
* },
|
||||||
async readdir({path}) {
|
* async readdir({path}) {
|
||||||
let route = findRoute(path);
|
* let route = findRoute(path);
|
||||||
if (route.entries) return { entries: await route.entries(path) };
|
* if (route.entries) return { entries: await route.entries(path) };
|
||||||
},
|
* },
|
||||||
async releasedir({path}) {
|
* async releasedir({path}) {
|
||||||
let route = findRoute(path);
|
* let route = findRoute(path);
|
||||||
if (route.releasedir) return route.releasedir(path);
|
* if (route.releasedir) return route.releasedir(path);
|
||||||
else return {};
|
* else return {};
|
||||||
}
|
* }
|
||||||
};
|
* };*/
|
||||||
|
|
||||||
let port;
|
let port;
|
||||||
async function onMessage(req) {
|
async function onMessage(req) {
|
||||||
console.log('req', req);
|
/* console.log('req', req);*/
|
||||||
|
|
||||||
let response = { op: req.op, error: unix.EIO };
|
let response = { op: req.op, error: unix.EIO };
|
||||||
/* console.time(req.op + ':' + req.path);*/
|
/* console.time(req.op + ':' + req.path);*/
|
||||||
try {
|
try {
|
||||||
response = await ops[req.op](req);
|
console.log(req.path, req.op, findRoute(req.path)[req.op]);
|
||||||
|
response = await findRoute(req.path)[req.op](req);
|
||||||
response.op = req.op;
|
response.op = req.op;
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -407,7 +430,7 @@ async function onMessage(req) {
|
||||||
}
|
}
|
||||||
/* console.timeEnd(req.op + ':' + req.path);*/
|
/* console.timeEnd(req.op + ':' + req.path);*/
|
||||||
|
|
||||||
console.log('resp', response);
|
/* console.log('resp', response);*/
|
||||||
port.postMessage(response);
|
port.postMessage(response);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
// This file should rarely need to be changed. (which is intentional,
|
||||||
|
// because it is a pain to program here, it's a pain to recompile and
|
||||||
|
// reload it, and it's a pain to debug it.) Most of the real meat of
|
||||||
|
// TabFS is on the extension side, not here.
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -238,7 +243,6 @@ static struct fuse_operations tabfs_filesystem_operations = {
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
/* system("killall -9 tabfs"); */
|
|
||||||
char killcmd[1000];
|
char killcmd[1000];
|
||||||
sprintf(killcmd, "pgrep tabfs | grep -v %d | xargs kill -9", getpid());
|
sprintf(killcmd, "pgrep tabfs | grep -v %d | xargs kill -9", getpid());
|
||||||
system(killcmd);
|
system(killcmd);
|
||||||
|
|
Loading…
Reference in a new issue