From 383096da003d4e3bbecdafd58278580e90d0b579 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Mon, 22 Mar 2021 23:25:38 -0700 Subject: [PATCH] extension,test: Move Router down, Router -> Routes. --- extension/background.js | 102 ++++++++++++++++++++-------------------- test/test.js | 12 ++--- 2 files changed, 57 insertions(+), 57 deletions(-) diff --git a/extension/background.js b/extension/background.js index f51be9f..6c1b9f5 100644 --- a/extension/background.js +++ b/extension/background.js @@ -61,8 +61,6 @@ const utf8ArrayToString = (function() { return utf8 => decoder.decode(utf8); })(); -const Router = {}; - const Cache = { // used when you open a file to cache the content we got from the // browser until you close that file. (so we can respond to @@ -147,7 +145,9 @@ const defineFile = (getData, setData) => ({ } }); -Router["/tabs/create"] = { +const Routes = {}; + +Routes["/tabs/create"] = { async write({buf}) { const url = buf.trim(); await browser.tabs.create({url}); @@ -156,7 +156,7 @@ Router["/tabs/create"] = { async truncate() { return {}; } }; -Router["/tabs/by-id"] = { +Routes["/tabs/by-id"] = { async readdir() { const tabs = await browser.tabs.query({}); return { entries: [".", "..", ...tabs.map(tab => String(tab.id))] }; @@ -176,21 +176,21 @@ Router["/tabs/by-id"] = { return (await browser.tabs.executeScript(tabId, {code}))[0]; }); - Router["/tabs/by-id/#TAB_ID/url.txt"] = withTab(tab => tab.url + "\n", buf => ({ url: buf })); - Router["/tabs/by-id/#TAB_ID/title.txt"] = withTab(tab => tab.title + "\n"); - Router["/tabs/by-id/#TAB_ID/text.txt"] = fromScript(`document.body.innerText`); - Router["/tabs/by-id/#TAB_ID/body.html"] = fromScript(`document.body.innerHTML`); + Routes["/tabs/by-id/#TAB_ID/url.txt"] = withTab(tab => tab.url + "\n", buf => ({ url: buf })); + Routes["/tabs/by-id/#TAB_ID/title.txt"] = withTab(tab => tab.title + "\n"); + Routes["/tabs/by-id/#TAB_ID/text.txt"] = fromScript(`document.body.innerText`); + Routes["/tabs/by-id/#TAB_ID/body.html"] = fromScript(`document.body.innerHTML`); // echo true > mnt/tabs/by-id/1644/active // cat mnt/tabs/by-id/1644/active - Router["/tabs/by-id/#TAB_ID/active"] = withTab(tab => JSON.stringify(tab.active) + '\n', + Routes["/tabs/by-id/#TAB_ID/active"] = withTab(tab => JSON.stringify(tab.active) + '\n', // WEIRD: we do startsWith because you might end up with buf // being "truee" (if it was "false", then someone wrote "true") buf => ({ active: buf.startsWith("true") })); })(); (function() { const evals = {}; - Router["/tabs/by-id/#TAB_ID/evals"] = { + Routes["/tabs/by-id/#TAB_ID/evals"] = { async readdir({path, tabId}) { return { entries: [".", "..", ...Object.keys(evals[tabId] || {}), @@ -204,7 +204,7 @@ Router["/tabs/by-id"] = { }; }, }; - Router["/tabs/by-id/#TAB_ID/evals/:FILENAME"] = { + Routes["/tabs/by-id/#TAB_ID/evals/:FILENAME"] = { // NOTE: eval runs in extension's content script, not in original page JS context async mknod({tabId, filename, mode}) { evals[tabId] = evals[tabId] || {}; @@ -239,7 +239,7 @@ Router["/tabs/by-id"] = { })(); (function() { const watches = {}; - Router["/tabs/by-id/#TAB_ID/watches"] = { + Routes["/tabs/by-id/#TAB_ID/watches"] = { async readdir({tabId}) { return { entries: [".", "..", ...Object.keys(watches[tabId] || [])] }; }, @@ -251,7 +251,7 @@ Router["/tabs/by-id"] = { }; }, }; - Router["/tabs/by-id/#TAB_ID/watches/:EXPR"] = { + Routes["/tabs/by-id/#TAB_ID/watches/:EXPR"] = { // NOTE: eval runs in extension's content script, not in original page JS context async mknod({tabId, expr, mode}) { watches[tabId] = watches[tabId] || {}; @@ -277,14 +277,14 @@ Router["/tabs/by-id"] = { }; })(); -Router["/tabs/by-id/#TAB_ID/window"] = { +Routes["/tabs/by-id/#TAB_ID/window"] = { // a symbolic link to /windows/[id for this window] async readlink({tabId}) { const tab = await browser.tabs.get(tabId); return { buf: "../../../windows/" + tab.windowId }; } }; -Router["/tabs/by-id/#TAB_ID/control"] = { +Routes["/tabs/by-id/#TAB_ID/control"] = { // echo remove > mnt/tabs/by-id/1644/control async write({tabId, buf}) { const command = buf.trim(); @@ -357,14 +357,14 @@ Router["/tabs/by-id/#TAB_ID/control"] = { // resources/ // TODO: scripts/ TODO: allow creation, eval immediately - Router["/tabs/by-id/#TAB_ID/debugger/resources"] = { + Routes["/tabs/by-id/#TAB_ID/debugger/resources"] = { async readdir({tabId}) { await TabManager.debugTab(tabId); await TabManager.enableDomainForTab(tabId, "Page"); const {frameTree} = await sendDebuggerCommand(tabId, "Page.getResourceTree", {}); return { entries: [".", "..", ...frameTree.resources.map(r => sanitize(String(r.url)))] }; } }; - Router["/tabs/by-id/#TAB_ID/debugger/resources/:SUFFIX"] = defineFile(async ({path, tabId, suffix}) => { + Routes["/tabs/by-id/#TAB_ID/debugger/resources/:SUFFIX"] = defineFile(async ({path, tabId, suffix}) => { await TabManager.debugTab(tabId); await TabManager.enableDomainForTab(tabId, "Page"); const {frameTree} = await sendDebuggerCommand(tabId, "Page.getResourceTree", {}); @@ -381,7 +381,7 @@ Router["/tabs/by-id/#TAB_ID/control"] = { } throw new UnixError(unix.ENOENT); }); - Router["/tabs/by-id/#TAB_ID/debugger/scripts"] = { + Routes["/tabs/by-id/#TAB_ID/debugger/scripts"] = { async opendir({tabId}) { await TabManager.debugTab(tabId); await TabManager.enableDomainForTab(tabId, "Debugger"); return { fh: 0 }; @@ -402,7 +402,7 @@ Router["/tabs/by-id/#TAB_ID/control"] = { } return scriptInfo; } - Router["/tabs/by-id/#TAB_ID/debugger/scripts/:FILENAME"] = defineFile(async ({tabId, filename}) => { + Routes["/tabs/by-id/#TAB_ID/debugger/scripts/:FILENAME"] = defineFile(async ({tabId, filename}) => { await TabManager.debugTab(tabId); await TabManager.enableDomainForTab(tabId, "Page"); await TabManager.enableDomainForTab(tabId, "Debugger"); @@ -419,7 +419,7 @@ Router["/tabs/by-id/#TAB_ID/control"] = { }); })(); -Router["/tabs/by-id/#TAB_ID/inputs"] = { +Routes["/tabs/by-id/#TAB_ID/inputs"] = { async readdir({tabId}) { // TODO: assign new IDs to inputs without them? const code = `Array.from(document.querySelectorAll('textarea, input[type=text]')) @@ -428,7 +428,7 @@ Router["/tabs/by-id/#TAB_ID/inputs"] = { return { entries: [".", "..", ...ids.map(id => `${id}.txt`)] }; } }; -Router["/tabs/by-id/#TAB_ID/inputs/:INPUT_ID.txt"] = defineFile(async ({tabId, inputId}) => { +Routes["/tabs/by-id/#TAB_ID/inputs/:INPUT_ID.txt"] = defineFile(async ({tabId, inputId}) => { const code = `document.getElementById('${inputId}').value`; const inputValue = (await browser.tabs.executeScript(tabId, {code}))[0]; if (inputValue === null) { throw new UnixError(unix.ENOENT); } /* FIXME: hack to deal with if inputId isn't valid */ @@ -439,7 +439,7 @@ Router["/tabs/by-id/#TAB_ID/inputs/:INPUT_ID.txt"] = defineFile(async ({tabId, i await browser.tabs.executeScript(tabId, {code}); }); -Router["/tabs/by-title"] = { +Routes["/tabs/by-title"] = { getattr() { return { st_mode: unix.S_IFDIR | 0777, // writable so you can delete tabs @@ -452,7 +452,7 @@ Router["/tabs/by-title"] = { return { entries: [".", "..", ...tabs.map(tab => sanitize(String(tab.title)) + "." + String(tab.id))] }; } }; -Router["/tabs/by-title/:TAB_TITLE.#TAB_ID"] = { +Routes["/tabs/by-title/:TAB_TITLE.#TAB_ID"] = { // TODO: date async readlink({tabId}) { // a symbolic link to /tabs/by-id/[id for this tab] return { buf: "../by-id/" + tabId }; @@ -462,7 +462,7 @@ Router["/tabs/by-title/:TAB_TITLE.#TAB_ID"] = { return {}; } }; -Router["/tabs/last-focused"] = { +Routes["/tabs/last-focused"] = { // a symbolic link to /tabs/by-id/[id for this tab] async readlink() { const id = (await browser.tabs.query({ active: true, lastFocusedWindow: true }))[0].id; @@ -470,13 +470,13 @@ Router["/tabs/last-focused"] = { } }; -Router["/windows"] = { +Routes["/windows"] = { async readdir() { const windows = await browser.windows.getAll(); return { entries: [".", "..", ...windows.map(window => String(window.id))] }; } }; -Router["/windows/last-focused"] = { +Routes["/windows/last-focused"] = { // a symbolic link to /windows/[id for this window] async readlink() { const windowId = (await browser.windows.getLastFocused()).id; @@ -492,11 +492,11 @@ Router["/windows/last-focused"] = { await browser.windows.update(windowId, writeHandler(buf)); } : undefined); - Router["/windows/#WINDOW_ID/focused"] = + Routes["/windows/#WINDOW_ID/focused"] = withWindow(window => JSON.stringify(window.focused) + '\n', buf => ({ focused: buf.startsWith('true') })); })(); -Router["/windows/#WINDOW_ID/visible-tab.png"] = { ...defineFile(async ({windowId}) => { +Routes["/windows/#WINDOW_ID/visible-tab.png"] = { ...defineFile(async ({windowId}) => { // screen capture is a window thing and not a tab thing because you // can only capture the visible tab for each window anyway; you // can't take a screenshot of just any arbitrary tab @@ -513,13 +513,13 @@ Router["/windows/#WINDOW_ID/visible-tab.png"] = { ...defineFile(async ({windowId } }; -Router["/extensions"] = { +Routes["/extensions"] = { async readdir() { const infos = await browser.management.getAll(); return { entries: [".", "..", ...infos.map(info => `${sanitize(info.name)}.${info.id}`)] }; } }; -Router["/extensions/:EXTENSION_TITLE.:EXTENSION_ID/enabled"] = { ...defineFile(async ({extensionId}) => { +Routes["/extensions/:EXTENSION_TITLE.:EXTENSION_ID/enabled"] = { ...defineFile(async ({extensionId}) => { const info = await browser.management.get(extensionId); return String(info.enabled) + '\n'; @@ -529,7 +529,7 @@ Router["/extensions/:EXTENSION_TITLE.:EXTENSION_ID/enabled"] = { ...defineFile(a // suppress truncate so it doesn't accidentally flip the state when you do, e.g., `echo true >` }), truncate() { return {}; } }; -Router["/runtime/reload"] = { +Routes["/runtime/reload"] = { async write({buf}) { await browser.runtime.reload(); return {size: stringToUtf8Array(buf).length}; @@ -544,20 +544,20 @@ Router["/runtime/reload"] = { // one level at a time so you know (for each parent) what all the // children will be. for (let i = 10; i >= 0; i--) { - for (let path of Object.keys(Router).filter(key => key.split("/").length === i)) { + for (let path of Object.keys(Routes).filter(key => key.split("/").length === i)) { path = path.substr(0, path.lastIndexOf("/")); if (path == '') path = '/'; - if (!Router[path]) { + if (!Routes[path]) { function depth(p) { return p === '/' ? 0 : (p.match(/\//g) || []).length; } // find all direct children - let entries = Object.keys(Router) + let entries = Object.keys(Routes) .filter(k => k.startsWith(path) && depth(k) === depth(path) + 1) .map(k => k.substr((path === '/' ? 0 : path.length) + 1).split('/')[0]); entries = [".", "..", ...new Set(entries)]; - Router[path] = { readdir() { return { entries }; } }; + Routes[path] = { readdir() { return { entries }; } }; } } // I also think it would be better to compute this stuff on the fly, @@ -566,9 +566,9 @@ for (let i = 10; i >= 0; i--) { } -for (let key in Router) { +for (let key in Routes) { // /tabs/by-id/#TAB_ID/url.txt -> RegExp \/tabs\/by-id\/(?[0-9]+)\/url.txt - Router[key].__regex = new RegExp( + Routes[key].__regex = new RegExp( '^' + key .split('/') .map(keySegment => keySegment @@ -579,8 +579,8 @@ for (let key in Router) { })) .join('/') + '$'); - Router[key].__match = function(path) { - const result = Router[key].__regex.exec(path); + Routes[key].__match = function(path) { + const result = Routes[key].__regex.exec(path); if (!result) { return; } const vars = {}; @@ -597,8 +597,8 @@ for (let key in Router) { // Fill in default implementations of fs ops: // if readdir -> directory -> add getattr, opendir, releasedir - if (Router[key].readdir) { - Router[key] = { + if (Routes[key].readdir) { + Routes[key] = { getattr() { return { st_mode: unix.S_IFDIR | 0755, @@ -608,11 +608,11 @@ for (let key in Router) { }, opendir({path}) { return { fh: 0 }; }, releasedir({path}) { return {}; }, - ...Router[key] + ...Routes[key] }; - } else if (Router[key].readlink) { - Router[key] = { + } else if (Routes[key].readlink) { + Routes[key] = { async getattr(req) { const st_size = (await this.readlink(req)).buf.length + 1; return { @@ -622,21 +622,21 @@ for (let key in Router) { st_size }; }, - ...Router[key] + ...Routes[key] }; - } else if (Router[key].read || Router[key].write) { - Router[key] = { + } else if (Routes[key].read || Routes[key].write) { + Routes[key] = { async getattr() { return { - st_mode: unix.S_IFREG | ((Router[key].read && 0444) | (Router[key].write && 0222)), + st_mode: unix.S_IFREG | ((Routes[key].read && 0444) | (Routes[key].write && 0222)), st_nlink: 1, st_size: 100 // FIXME }; }, open() { return { fh: 0 }; }, release() { return {}; }, - ...Router[key] + ...Routes[key] }; } } @@ -647,7 +647,7 @@ function tryMatchRoute(path) { throw new UnixError(unix.ENOTSUP); } - for (let route of Object.values(Router)) { + for (let route of Object.values(Routes)) { const vars = route.__match(path); if (vars) { return [route, vars]; } } @@ -733,7 +733,7 @@ function tryConnect() { if (typeof process === 'object') { // we're running in node (as part of a test) // return everything they might want to test - module.exports = {Router, tryMatchRoute}; + module.exports = {Routes, tryMatchRoute}; } else { tryConnect(); diff --git a/test/test.js b/test/test.js index 59aa7c9..3494468 100644 --- a/test/test.js +++ b/test/test.js @@ -3,21 +3,21 @@ const assert = require('assert'); // mock chrome namespace global.chrome = {}; // run background.js -const {Router, tryMatchRoute} = require('../extension/background'); +const {Routes, tryMatchRoute} = require('../extension/background'); (async () => { - const tabRoute = await Router['/tabs/by-id/#TAB_ID'].readdir(); + const tabRoute = await Routes['/tabs/by-id/#TAB_ID'].readdir(); assert(['.', '..', 'url.txt', 'title.txt', 'text.txt'] .every(file => tabRoute.entries.includes(file))); - assert.deepEqual(await Router['/'].readdir(), + assert.deepEqual(await Routes['/'].readdir(), { entries: ['.', '..', 'windows', 'extensions', 'tabs', 'runtime'] }); - assert.deepEqual(await Router['/tabs'].readdir(), + assert.deepEqual(await Routes['/tabs'].readdir(), { entries: ['.', '..', 'create', 'by-id', 'by-title', 'last-focused'] }); - assert.deepEqual(tryMatchRoute('/'), [Router['/'], {}]); + assert.deepEqual(tryMatchRoute('/'), [Routes['/'], {}]); assert.deepEqual(tryMatchRoute('/tabs/by-id/10/url.txt'), - [Router['/tabs/by-id/#TAB_ID/url.txt'], {tabId: 10}]); + [Routes['/tabs/by-id/#TAB_ID/url.txt'], {tabId: 10}]); })();