This page is automatically generated from extension/background.js in the TabFS source code.

It documents each of the folders and files that TabFS serves up from your browser.

Variables here, like :TAB_TITLE and #TAB_ID, are stand-ins for concrete values of what you actually have open in your browser.

(work in progress)

📄 tabs/create
Create a new tab.
Usage examples
  • echo "https://www.google.com" > tabs/create
Source code (on GitHub)
Routes["/tabs/create"] = {
  description: 'Create a new tab.',
  usage: 'echo "https://www.google.com" > $0',
  async write({buf}) {
    const url = buf.trim();
    await browser.tabs.create({url});
    return {size: stringToUtf8Array(buf).length};
  },
  async truncate() { return {}; }
};
📁 tabs/by-title
Open tabs, organized by title; each subfolder represents an open tab.
Usage examples
  • ls tabs/by-title
Source code (on GitHub)
Routes["/tabs/by-title"] = {
  description: 'Open tabs, organized by title; each subfolder represents an open tab.',
  usage: 'ls $0',
  getattr() {
    return {
      st_mode: unix.S_IFDIR | 0777, // writable so you can delete tabs
      st_nlink: 3,
      st_size: 0,
    };
  },
  async readdir() {
    const tabs = await browser.tabs.query({});
    return { entries: [".", "..", ...tabs.map(tab => sanitize(String(tab.title)) + "." + String(tab.id))] };
  }
};
📄 tabs/by-title/:TAB_TITLE.#TAB_ID
Represents one open tab. It's a symbolic link to the folder /tabs/by-id/#TAB_ID.
Usage examples
  • rm tabs/by-title/:TAB_TITLE.#TAB_ID
Source code (on GitHub)
Routes["/tabs/by-title/:TAB_TITLE.#TAB_ID"] = {
  description: `Represents one open tab.
It's a symbolic link to the folder /tabs/by-id/#TAB_ID.`,
  // TODO: date
  usage: ['rm $0'],
  async readlink({tabId}) {
    return { buf: "../by-id/" + tabId };
  },
  async unlink({tabId}) {
    await browser.tabs.remove(tabId);
    return {};
  }
};
📄 tabs/last-focused
Represents the most recently focused tab. It's a symbolic link to the folder /tabs/by-id/[ID of most recently focused tab].
No usage examples found!
Source code (on GitHub)
Routes["/tabs/last-focused"] = {
  description: `Represents the most recently focused tab.
It's a symbolic link to the folder /tabs/by-id/[ID of most recently focused tab].`,
  async readlink() {
    const id = (await browser.tabs.query({ active: true, lastFocusedWindow: true }))[0].id;
    return { buf: "by-id/" + id };
  }
};
📁 tabs/by-id
Open tabs, organized by ID; each subfolder represents an open tab.
Usage examples
  • ls tabs/by-id
Source code (on GitHub)
Routes["/tabs/by-id"] = {
  description: `Open tabs, organized by ID; each subfolder represents an open tab.`,
  usage: 'ls $0',
  async readdir() {
    const tabs = await browser.tabs.query({});
    return { entries: [".", "..", ...tabs.map(tab => String(tab.id))] };
  }
};
📄 tabs/by-id/#TAB_ID/url.txt
Text file containing the current URL of this tab.
Usage examples
  • cat tabs/by-id/#TAB_ID/url.txt
  • echo "https://www.google.com" > tabs/by-id/#TAB_ID/url.txt
Source code (on GitHub)
  Routes["/tabs/by-id/#TAB_ID/url.txt"] = {
    description: `Text file containing the current URL of this tab.`,
    usage: ['cat $0',
            'echo "https://www.google.com" > $0'],
    ...routeForTab(tab => tab.url + "\n",
                   buf => ({ url: buf }))
  };
📄 tabs/by-id/#TAB_ID/title.txt
Text file containing the current title of this tab.
Usage examples
  • cat tabs/by-id/#TAB_ID/title.txt
Source code (on GitHub)
  Routes["/tabs/by-id/#TAB_ID/title.txt"] = {
    description: `Text file containing the current title of this tab.`,
    usage: 'cat $0',
    ...routeForTab(tab => tab.title + "\n")
  };
📄 tabs/by-id/#TAB_ID/text.txt
Text file containing the current body text of this tab.
Usage examples
  • cat tabs/by-id/#TAB_ID/text.txt
Source code (on GitHub)
  Routes["/tabs/by-id/#TAB_ID/text.txt"] = {
    description: `Text file containing the current body text of this tab.`,
    usage: 'cat $0',
    ...routeFromScript(`document.body.innerText`)
  };
📄 tabs/by-id/#TAB_ID/body.html
Text file containing the current body HTML of this tab.
Usage examples
  • cat tabs/by-id/#TAB_ID/body.html
Source code (on GitHub)
  Routes["/tabs/by-id/#TAB_ID/body.html"] = {
    description: `Text file containing the current body HTML of this tab.`,
    usage: 'cat $0',
    ...routeFromScript(`document.body.innerHTML`)
  };
📄 tabs/by-id/#TAB_ID/active
Text file containing `true` or `false` depending on whether this tab is active in its window.
Usage examples
  • cat tabs/by-id/#TAB_ID/active
  • echo true > tabs/by-id/#TAB_ID/active
Source code (on GitHub)
  Routes["/tabs/by-id/#TAB_ID/active"] = {
    description: 'Text file containing `true` or `false` depending on whether this tab is active in its window.',
    usage: ['cat $0',
            'echo true > $0'],
    ...routeForTab(
      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") })
    )
  };
📁 tabs/by-id/#TAB_ID/evals
Add JavaScript files to this folder to evaluate them in the tab.
Usage examples
  • ls tabs/by-id/#TAB_ID/evals
Source code (on GitHub)
  Routes["/tabs/by-id/#TAB_ID/evals"] = {
    ...evals.routeForRoot,
    description: `Add JavaScript files to this folder to evaluate them in the tab.`,
    usage: 'ls $0'
  };
📄 tabs/by-id/#TAB_ID/evals/:FILENAME
No description found!
Usage examples
  • echo "2 + 2" > tabs/by-id/#TAB_ID/evals/twoplustwo.js
  • cat tabs/by-id/#TAB_ID/evals/twoplustwo.js.result
Source code (on GitHub)
  Routes["/tabs/by-id/#TAB_ID/evals/:FILENAME"] = {
    ...evals.routeForFilename,
    // FIXME: use $0 here
    usage: ['echo "2 + 2" > tabs/by-id/#TAB_ID/evals/twoplustwo.js',
            'cat tabs/by-id/#TAB_ID/evals/twoplustwo.js.result'],
    async write(req) {
      const ret = await evals.routeForFilename.write(req);
      const code = evals.directory[req.path];
      evals.directory[req.path + '.result'] = JSON.stringify((await browser.tabs.executeScript(req.tabId, {code}))[0]) + '\n';
      return ret;
    }
  };
📁 tabs/by-id/#TAB_ID/watches
Put a file in this folder with a JS expression as its filename. Read that file to evaluate and return the current value of that JS expression.
Usage examples
  • ls tabs/by-id/#TAB_ID/watches
Source code (on GitHub)
  Routes["/tabs/by-id/#TAB_ID/watches"] = {
    description: `Put a file in this folder with a JS expression as its filename.
Read that file to evaluate and return the current value of that JS expression.`,
    usage: 'ls $0',
    async readdir({tabId}) {
      return { entries: [".", "..", ...Object.keys(watches[tabId] || [])] };
    },
    getattr() {
      return {
        st_mode: unix.S_IFDIR | 0777, // writable so you can create/rm watches
        st_nlink: 3,
        st_size: 0,
      };
    },
  };
📄 tabs/by-id/#TAB_ID/watches/:EXPR
A file with a JS expression :EXPR as its filename.
Usage examples
  • touch '/tabs/by-id/#TAB_ID/watches/2+2' && cat '/tabs/by-id/#TAB_ID/watches/2+2'
Source code (on GitHub)
  Routes["/tabs/by-id/#TAB_ID/watches/:EXPR"] = {
    description: `A file with a JS expression :EXPR as its filename.`,
    usage: `touch '/tabs/by-id/#TAB_ID/watches/2+2' && cat '/tabs/by-id/#TAB_ID/watches/2+2'`,
    // NOTE: eval runs in extension's content script, not in original page JS context
    async mknod({tabId, expr, mode}) {
      watches[tabId] = watches[tabId] || {};
      watches[tabId][expr] = async function() {
        return (await browser.tabs.executeScript(tabId, {code: expr}))[0];
      };
      return {};
    },
    async unlink({tabId, expr}) {
      delete watches[tabId][expr]; // TODO: also delete watches[tabId] if empty
      return {};
    },

    ...makeRouteWithContents(async ({tabId, expr}) => {
      if (!watches[tabId] || !(expr in watches[tabId])) { throw new UnixError(unix.ENOENT); }
      return JSON.stringify(await watches[tabId][expr]()) + '\n';

    }, () => {
      // setData handler -- only providing this so that getattr reports
      // that the file is writable, so it can be deleted without annoying prompt.
      throw new UnixError(unix.EPERM);
    })
  };
📄 tabs/by-id/#TAB_ID/window
The window that this tab lives in; a symbolic link to the folder /windows/[id for this window].
No usage examples found!
Source code (on GitHub)
Routes["/tabs/by-id/#TAB_ID/window"] = {
  description: `The window that this tab lives in;
a symbolic link to the folder /windows/[id for this window].`,
  async readlink({tabId}) {
    const tab = await browser.tabs.get(tabId);
    return { buf: "../../../windows/" + tab.windowId };
  }
};
📄 tabs/by-id/#TAB_ID/control
Write control commands to this file to control this tab; see https://developer.chrome.com/extensions/tabs.
Usage examples
  • echo remove > tabs/by-id/#TAB_ID/control
  • echo reload > tabs/by-id/#TAB_ID/control
  • echo goForward > tabs/by-id/#TAB_ID/control
  • echo goBack > tabs/by-id/#TAB_ID/control
  • echo discard > tabs/by-id/#TAB_ID/control
Source code (on GitHub)
Routes["/tabs/by-id/#TAB_ID/control"] = {
  description: `Write control commands to this file to control this tab;
see https://developer.chrome.com/extensions/tabs.`,
  usage: ['echo remove > $0',
          'echo reload > $0',
          'echo goForward > $0',
          'echo goBack > $0',
          'echo discard > $0'],
  async write({tabId, buf}) {
    const command = buf.trim();
    await browser.tabs[command](tabId);
    return {size: stringToUtf8Array(buf).length};
  },
  async truncate({size}) { return {}; }
};
📁 tabs/by-id/#TAB_ID/inputs
Contains a file for each text input and textarea on this page (as long as it has an ID, currently).
No usage examples found!
Source code (on GitHub)
Routes["/tabs/by-id/#TAB_ID/inputs"] = {
  description: `Contains a file for each text input and textarea on this page (as long as it has an ID, currently).`,
  async readdir({tabId}) {
    // TODO: assign new IDs to inputs without them?
    const code = `Array.from(document.querySelectorAll('textarea, input[type=text]'))
                    .map(e => e.id).filter(id => id)`;
    const ids = (await browser.tabs.executeScript(tabId, {code}))[0];
    return { entries: [".", "..", ...ids.map(id => `${id}.txt`)] };
  }
};
📄 tabs/by-id/#TAB_ID/inputs/:INPUT_ID.txt
No description found!
No usage examples found!
Source code (on GitHub)
Routes["/tabs/by-id/#TAB_ID/inputs/:INPUT_ID.txt"] = makeRouteWithContents(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 */
  return inputValue;

}, async ({tabId, inputId}, buf) => {
  const code = `document.getElementById('${inputId}').value = unescape('${escape(buf)}')`;
  await browser.tabs.executeScript(tabId, {code});
});
📁 windows
No description found!
No usage examples found!
Source code (on GitHub)
Routes["/windows"] = {
  async readdir() {
    const windows = await browser.windows.getAll();
    return { entries: [".", "..", ...windows.map(window => String(window.id))] };
  }
};
📄 windows/last-focused
A symbolic link to /windows/[id for the last focused window].
No usage examples found!
Source code (on GitHub)
Routes["/windows/last-focused"] = {
  description: `A symbolic link to /windows/[id for the last focused window].`,
  async readlink() {
    const windowId = (await browser.windows.getLastFocused()).id;
    return { buf: windowId };
  }
};
📄 windows/#WINDOW_ID/focused
No description found!
No usage examples found!
No source code found!
📄 windows/#WINDOW_ID/visible-tab.png
No description found!
No usage examples found!
Source code (on GitHub)
Routes["/windows/#WINDOW_ID/visible-tab.png"] = { ...makeRouteWithContents(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
  const dataUrl = await browser.tabs.captureVisibleTab(windowId, {format: 'png'});
  return Uint8Array.from(atob(dataUrl.substr(("data:image/png;base64,").length)),
                         c => c.charCodeAt(0));

}), async getattr() {
  return {
    st_mode: unix.S_IFREG | 0444,
    st_nlink: 1,
    st_size: 10000000 // hard-code to 10MB for now
  };
} };
📁 extensions
No description found!
No usage examples found!
Source code (on GitHub)
Routes["/extensions"] = {  
  async readdir() {
    const infos = await browser.management.getAll();
    return { entries: [".", "..", ...infos.map(info => `${sanitize(info.name)}.${info.id}`)] };
  }
};
📄 extensions/:EXTENSION_TITLE.:EXTENSION_ID/enabled
No description found!
No usage examples found!
Source code (on GitHub)
Routes["/extensions/:EXTENSION_TITLE.:EXTENSION_ID/enabled"] = { ...makeRouteWithContents(async ({extensionId}) => {
  const info = await browser.management.get(extensionId);
  return String(info.enabled) + '\n';

}, async ({extensionId}, buf) => {
  await browser.management.setEnabled(extensionId, buf.trim() === "true");

  // suppress truncate so it doesn't accidentally flip the state when you do, e.g., `echo true >`
}), truncate() { return {}; } };
📄 runtime/reload
No description found!
No usage examples found!
Source code (on GitHub)
Routes["/runtime/reload"] = {
  async write({buf}) {
    await browser.runtime.reload();
    return {size: stringToUtf8Array(buf).length};
  },
  truncate() { return {}; }
};
📄 runtime/routes.html
No description found!
No usage examples found!
No source code found!