The problem#
Previously, I showed how to get Firefox to show just the web content without any of the window borders or toolbars. But there's an obvious problem: those UI elements are actually useful for doing things with the browser. We can give a single URL as an argument when we start the browser, and that may be good enough for some use-cases, but what if we want to have more control over what the browser is displaying?
The solution#
Firefox has a feature for running automated tests called Marionette which we can use for automating Firefox outside of the context of running tests. There's an official Python client:
$ pip install marionette_driver
$ firefox --marionette &
$ python
>>> from marionette_driver.marionette import Marionette
>>> client = Marionette('localhost', port=2828)
>>> client.start_session()
{'browserName': 'firefox', ... }
>>> client.navigate('https://example.com/')
If it works, you should see Firefox load
the URL https://example.com/
.
You can find more information on the available commands on the basics page and the documentation.
The details#
Running Firefox#
If Firefox is already running, then firefox --marionette
will ignore
the --marionette
part and just open a new window in your existing
Firefox session. You can use -no-remote
to tell Firefox to not connect
to an existing session. You likely also want to use -P PROFILE_NAME
to
specify a different profile from your default one:
firefox --marionette -no-remote -P "Other Profile"
Connecting to Firefox#
I had some trouble getting Marionette to connect in a script where I
started Firefox in the background and immediately tried to connect
to it. While I can't currently manage to recreate the issue, I ended
up putting in a few seconds of time.sleep()
before the call to
client.start_session()
to fix it. Now that I'm trying to recreate the
error, it seems like the timing doesn't matter and, in fact, it works to
run client.start_session()
before starting Firefox and it will block
until it finds a Firefox instance to connect to.
Do note that only one Marionette client can be connected at a time. If another tries to connect, it will block until the first disconnects.
Useful commands#
Here's some useful commands for managing Firefox windows:
client.navigate(url)
: equivalent to puttingurl
in the URL bar and pressing Enter.client.get_url()
: get the URL of the current window.client.open("window", True, False)
: open a new window (or change"window"
to"tab"
to open a new tab). The documentation implies this will focus that new tab, but this does not appear to be case, at least if the window is not already focused.client.close()
: close the current window.client.set_window_rect(x, y, height, width)
: resize window. Note the weird order of the arguments. Theclient.window_rect
property will get the current size.client.fullscreen()
: enter fullscreen mode. The documentation implies it will also exit fullscreen mode, but that's not happening for me. As a workaround,set_window_rect()
will exit fullscreen.client.switch_to_window(handle)
: Sets the current window to the window identified byhandle
. The documentation implies this will focus that window, but that does not seem to be happening for me.
The following code will generate a list of all windows with their handles, positions, and URLs:
original_window = client.current_window_handle
tabs = []
for handle in client.window_handles:
client.switch_to_window(handle)
tabs.append({
"handle": handle,
"rect": client.window_rect,
"url": client.get_url(),
})
client.switch_to_window(original_window)
# do something with tabs
Comments
Have something to add? Post a comment by sending an email to comments@aweirdimagination.net. You may use Markdown for formatting.
There are no comments yet.