How to make firefox read stdin?

You can use data URIs, like this:

echo '<h1>hello, world</h1>' |firefox "data:text/html;base64,$(base64 -w 0 <&0)"

&0 is the file descriptor for stdin, so it encodes stdin to base64, then interpolates that into the data URI.

The same trick works for other browsers, too:

echo '<h1>hello, world</h1>' |chromium "data:text/html;base64,$(base64 -w 0 <&0)"
echo '<h1>hello, world</h1>' |opera    "data:text/html;base64,$(base64 -w 0 <&0)"

If you want, you can put the second part in a bash script (I'll call it pipefox.sh):

#!/bin/bash
firefox "data:text/html;base64,$(base64 -w 0 <&0)"

Now you can do:

echo '<h1>hello, world</h1>' |pipefox.sh

The short answer is, you're better off writing a temporary file and opening that. Getting pipes to work properly is more complicated and probably won't give you any extra advantages. That said, here's what I've found.

If your firefox command is actually starting Firefox instead of talking with an already-running Firefox instance, you can do this:

echo '<h1>hello, world</h1>' | firefox /dev/fd/0

Which tells Firefox explicitly to read its standard input, which is where the pipe is putting its data. But if Firefox is already running, the firefox command is just going to pass that name to the main Firefox process, which will read its own standard input, which probably won't give it anything and certainly isn't connected to your pipe.

Furthermore, when reading from a pipe, Firefox buffers things pretty heavily, so it's not going to update the page each time you give it a new line of HTML, if that's what you're going for. Try closing Firefox and running:

cat | firefox /dev/fd/0

(N.B. you do actually need the cat here.) Paste some long lines into your shell window repeatedly until Firefox decides to update the page, and you can see how much data it takes. Now send an End-Of-File signal by hitting Ctrl+D on a new line, and watch Firefox update instantly. But then you can't add any more data.

So best is probably:

echo '<h1>hello, world</h1>' >my_temporary_file; firefox my_temporary_file

I found this:

bcat -- pipe to browser utility

... to install on Ubuntu Natty, I did:

sudo apt-get install rubygems1.8
sudo gem install bcat
# to call
ruby -rubygems /var/lib/gems/1.8/gems/bcat-0.6.2/bin/bcat
echo "<b>test</b>" | ruby -rubygems /var/lib/gems/1.8/gems/bcat-0.6.2/bin/bcat

I thought it works with its own browser - but running the above opened a new tab in an already running Firefox, pointing at a localhost address http://127.0.0.1:53718/btest ... With bcat installation you can also do:

tail -f /var/log/syslog | ruby -rubygems /var/lib/gems/1.8/gems/bcat-0.6.2/bin/btee

... a tab will again open, but Firefox will keep showing the loading icon (and apparently would update the page when syslog updates).

The bcat homepage also references the uzbl browser, which can apparently handle stdin - but for its own commands (should probably look into this more, though)


EDIT: As I needed something like this badly (mostly to view HTML tables with data generated on the fly (and my Firefox is getting really slow to be useful with bcat), I tried with a custom solution. Since I use ReText, I already had installed python-qt4 and WebKit bindings (and dependencies) on my Ubuntu. So, I put together a Python/PyQt4/QWebKit script - which works like bcat (not like btee), but with its own browser window - called Qt4WebKit_singleinst_stdin.py (or qwksisi for short):

  • http://sdaaubckp.svn.sourceforge.net/viewvc/sdaaubckp/single-scripts/Qt4WebKit_singleinst_stdin.py?view=markup

Basically, with the downloaded script (and dependencies) you can alias it in a bash terminal like this:

$ alias qwksisi="python /path/to/Qt4WebKit_singleinst_stdin.py"

... and in one terminal (after aliasing), qwksisi will raise the master browser window; while in another terminal (again after aliasing), one could do the following to obtain stdin data:

$ echo "<h1>Hello World</h1>" | qwksisi - 

... as shown below:

qwksisi

Don't forget the - at end to refer to stdin; otherwise a local filename can be used as last argument, as well.

Basically, the problem here is to solve:

  • single instance problem (so first run of script becomes a "master" and raises a browser window - while subsequent runs simply pass data to master and exit)
  • interprocess communication for sharing variables (so exiting processes can pass data to the master browser window)
  • Timer update in the master that checks for new content, and updates the browser window if new content arrived.

As such, the same could be implemented in, say, Perl with Gtk bindings and WebKit (or other browser component). I wonder, though, if the XUL framework by Mozilla could be used to implement the same functionality - I guess in that case, one would work with the Firefox browser component.

Tags:

Firefox