Played around a bit with geckodriver
and Wireshark
:
Start Firefox with --marionette
; personally I like to add --headless --no-remote --profile $(mktemp -d)
, but this is up to you! Opens FireFox listening on port 2828 (there is a way to change this, but I'm not 100% sure how).
The Marionette protocol is as follows:
- each message is a length-prefixed json message without newline (so for instance, when you connect
telnet localhost 2828
, you're greeted by 50:{"applicationType":"gecko","marionetteProtocol":3}
, the 50
meaning the json is 50 bytes long.
- each message (except for the first one) are a json array of 4 items:
[0, messageId, command, body]
for a request, where messageId
is an int, command
a string and body
an object. Example (with length prefix) 31:[0,1,"WebDriver:NewSession",{}]
[1, messageId, error, reply]
for a reply. Here messageId
is the id the reply was to, and either error
or result
is null (depending on whether there is an error). E.g. 697:[1,1,null,{"sessionId":"d9dbe...", ..., "proxy":{}}}]
- A full list of all commands can be found in the Marionette source code, and it seems to me that all functions there are pretty well documented. For one thing, it seems that they expose all webdriver functions under
WebDriver:*
.
Update: it seems that https://bugzilla.mozilla.org/show_bug.cgi?id=1421766 is also struggling with finding the right marionette port/setting the port. The way I now do it:
TEMPD="$(mktemp -d)"
echo 'user_pref("marionette.port", 0);' > "${TEMPD}"/prefs.js
/Applications/Firefox.app/Contents/MacOS/firefox-bin --marionette --headless --no-remote --profile "${TEMPD}" &
PID=$!
MARIONETTE_PORT=""
while [ -z "$MARIONETTE_PORT" ]; do
sleep 1
MARIONETTE_PORT=$(lsof -a -p $PID -s TCP:LISTEN -i4 -nP | grep -oE ':\d+ \(LISTEN\)' | grep -oE '\d+')
done
echo "Marionette started on port $MARIONETTE_PORT"
fg
(Giving port 0 makes Firefox choose a random empty port. The command works for MacOS; will probably need some tweaking on Linux (I think the arguments to lsof
are slightly different; also Linux grep
has lookbehind/lookahead, so you could replace the double grep
by a single one).
UPDATE 2
Since Firefox will write the Marionette port it uses to "${TEMPD}"/prefs.js
, one does not even need to do "fancy" things with lsof
; rather just check that file:
TEMPD="$(mktemp -d)"
echo 'user_pref("marionette.port", 0);' > "${TEMPD}"/prefs.js
/Applications/Firefox.app/Contents/MacOS/firefox-bin --marionette --headless --no-remote --profile "${TEMPD}" &
MARIONETTE_PORT=""
while [ -z "$MARIONETTE_PORT" ]; do
sleep 1
MARIONETTE_PORT=$(cat "${TEMPD}"/prefs.js | grep 'user_pref("marionette.port"' | grep -oE '[1-9][0-9]*')
done
echo "Marionette started on port $MARIONETTE_PORT"
fg