Firefox-Marionette

 view release on metacpan or  search on metacpan

README.md  view on Meta::CPAN

    MII..
    -----END CERTIFICATE-----
    _PEM_
    my $firefox = Firefox::Marionette->new()->add_certificate(string => $pem_encoded_string);

## add\_cookie

accepts a single [cookie](https://metacpan.org/pod/Firefox::Marionette::Cookie) object as the first parameter and adds it to the current cookie jar.  This method returns [itself](https://metacpan.org/pod/Firefox::Marionette) to aid in chaining method...

This method throws an exception if you try to [add a cookie for a different domain than the current document](https://developer.mozilla.org/en-US/docs/Web/WebDriver/Errors/InvalidCookieDomain).

## add\_header

accepts a hash of HTTP headers to include in every future HTTP Request.

    use Firefox::Marionette();
    use UUID();

    my $firefox = Firefox::Marionette->new();
    my $uuid = UUID::uuid();
    $firefox->add_header( 'Track-my-automated-tests' => $uuid );
    $firefox->go('https://metacpan.org/');

these headers are added to any existing headers.  To clear headers, see the [delete\_header](#delete_header) method

    use Firefox::Marionette();

    my $firefox = Firefox::Marionette->new()->delete_header( 'Accept' )->add_header( 'Accept' => 'text/perl' )->go('https://metacpan.org/');

will only send out an [Accept](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept) header that looks like `Accept: text/perl`.

    use Firefox::Marionette();

    my $firefox = Firefox::Marionette->new()->add_header( 'Accept' => 'text/perl' )->go('https://metacpan.org/');

by itself, will send out an [Accept](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept) header that may resemble `Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8, text/perl`. This method returns [itse...

## add\_login

accepts a hash of the following keys;

- host - The scheme + hostname of the page where the login applies, for example 'https://www.example.org'.
- user - The username for the login.
- password - The password for the login.
- origin - The scheme + hostname that the form-based login [was submitted to](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form#attr-action).  Forms with no [action attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/for...
- realm - The HTTP Realm for which the login was requested. When an HTTP server sends a 401 result, the WWW-Authenticate header includes a realm. See [RFC 2617](https://datatracker.ietf.org/doc/html/rfc2617).  If the realm is not specified, or it was...
- user\_field - The name attribute for the username input in a form. Non-form logins should not specify this field.
- password\_field - The name attribute for the password input in a form. Non-form logins should not specify this field.

or a [Firefox::Marionette::Login](https://metacpan.org/pod/Firefox::Marionette::Login) object as the first parameter and adds the login to the Firefox login database.

    use Firefox::Marionette();
    use UUID();

    my $firefox = Firefox::Marionette->new();

    # for http auth logins

    my $http_auth_login = Firefox::Marionette::Login->new(host => 'https://pause.perl.org', user => 'AUSER', password => 'qwerty', realm => 'PAUSE');
    $firefox->add_login($http_auth_login);
    $firefox->go('https://pause.perl.org/pause/authenquery')->accept_alert(); # this goes to the page and submits the http auth popup

    # for form based login

    my $form_login = Firefox::Marionette::Login(host => 'https://github.com', user => 'me2@example.org', password => 'uiop[]', user_field => 'login', password_field => 'password');
    $firefox->add_login($form_login);

    # or just directly

    $firefox->add_login(host => 'https://github.com', user => 'me2@example.org', password => 'uiop[]', user_field => 'login', password_field => 'password');

Note for HTTP Authentication, the [realm](https://datatracker.ietf.org/doc/html/rfc2617#section-2) must perfectly match the correct [realm](https://datatracker.ietf.org/doc/html/rfc2617#section-2) supplied by the server.

This method returns [itself](https://metacpan.org/pod/Firefox::Marionette) to aid in chaining methods.

## add\_site\_header

accepts a host name and a hash of HTTP headers to include in every future HTTP Request that is being sent to that particular host.

    use Firefox::Marionette();
    use UUID();

    my $firefox = Firefox::Marionette->new();
    my $uuid = UUID::uuid();
    $firefox->add_site_header( 'metacpan.org', 'Track-my-automated-tests' => $uuid );
    $firefox->go('https://metacpan.org/');

these headers are added to any existing headers going to the metacpan.org site, but no other site.  To clear site headers, see the [delete\_site\_header](#delete_site_header) method

## add\_webauthn\_authenticator

accepts a hash of the following keys;

- has\_resident\_key - boolean value to indicate if the authenticator will support [client side discoverable credentials](https://www.w3.org/TR/webauthn-2/#client-side-discoverable-credential)
- has\_user\_verification - boolean value to determine if the [authenticator](https://www.w3.org/TR/webauthn-2/#virtual-authenticators) supports [user verification](https://www.w3.org/TR/webauthn-2/#user-verification).
- is\_user\_consenting - boolean value to determine the result of all [user consent](https://www.w3.org/TR/webauthn-2/#user-consent) [authorization gestures](https://www.w3.org/TR/webauthn-2/#authorization-gesture), and by extension, any [test of use...
- is\_user\_verified - boolean value to determine the result of [User Verification](https://www.w3.org/TR/webauthn-2/#user-verification) performed on the [Virtual Authenticator](https://www.w3.org/TR/webauthn-2/#virtual-authenticators). If set to tru...
- protocol - the [protocol](https://metacpan.org/pod/Firefox::Marionette::WebAuthn::Authenticator#protocol) spoken by the authenticator.  This may be [CTAP1\_U2F](https://metacpan.org/pod/Firefox::Marionette::WebAuthn::Authenticator#CTAP1_U2F), [CTAP...
- transport - the [transport](https://metacpan.org/pod/Firefox::Marionette::WebAuthn::Authenticator#transport) simulated by the authenticator.  This may be [BLE](https://metacpan.org/pod/Firefox::Marionette::WebAuthn::Authenticator#BLE), [HYBRID](htt...

It returns the newly created [authenticator](https://metacpan.org/pod/Firefox::Marionette::WebAuthn::Authenticator).

    use Firefox::Marionette();
    use Crypt::URandom();

    my $user_name = MIME::Base64::encode_base64( Crypt::URandom::urandom( 10 ), q[] ) . q[@example.com];
    my $firefox = Firefox::Marionette->new( webauthn => 0 );
    my $authenticator = $firefox->add_webauthn_authenticator( transport => Firefox::Marionette::WebAuthn::Authenticator::INTERNAL(), protocol => Firefox::Marionette::WebAuthn::Authenticator::CTAP2() );
    $firefox->go('https://webauthn.io');
    $firefox->find_id('input-email')->type($user_name);
    $firefox->find_id('register-button')->click();
    $firefox->await(sub { sleep 1; $firefox->find_class('alert-success'); });
    $firefox->find_id('login-button')->click();
    $firefox->await(sub { sleep 1; $firefox->find_class('hero confetti'); });

## add\_webauthn\_credential

accepts a hash of the following keys;

- authenticator - contains the [authenticator](https://metacpan.org/pod/Firefox::Marionette::WebAuthn::Authenticator) that the credential will be added to.  If this parameter is not supplied, the credential will be added to the default authenticator,...
- host - contains the domain that this credential is to be used for.  In the language of [WebAuthn](https://www.w3.org/TR/webauthn-2), this field is referred to as the [relying party identifier](https://www.w3.org/TR/webauthn-2/#relying-party-identif...

README.md  view on Meta::CPAN

returns the version for the Marionette protocol.  Current most recent version is '3'.

## maximise

maximises the firefox window. This method returns [itself](https://metacpan.org/pod/Firefox::Marionette) to aid in chaining methods.

## mime\_types

returns a list of MIME types that will be downloaded by firefox and made available from the [downloads](#downloads) method

    use Firefox::Marionette();
    use v5.10;

    my $firefox = Firefox::Marionette->new(mime_types => [ 'application/pkcs10' ])

    foreach my $mime_type ($firefox->mime_types()) {
        say $mime_type;
    }

## minimise

minimises the firefox window. This method returns [itself](https://metacpan.org/pod/Firefox::Marionette) to aid in chaining methods.

## mouse\_down

accepts a parameter describing which mouse button the method should apply to ([left](https://metacpan.org/pod/Firefox::Marionette::Buttons#LEFT), [middle](https://metacpan.org/pod/Firefox::Marionette::Buttons#MIDDLE) or [right](https://metacpan.org/p...

## mouse\_move

accepts a [element](https://metacpan.org/pod/Firefox::Marionette::Element) parameter, or a `( x => 0, y => 0 )` type hash manually describing exactly where to move the mouse to and returns an action for use in the [perform](#perform) method that corr...

- origin - the origin of the C(<x => 0, y => 0)> co-ordinates.  Should be either `viewport`, `pointer` or an [element](https://metacpan.org/pod/Firefox::Marionette::Element).
- duration - Number of milliseconds over which to distribute the move. If not defined, the duration defaults to 0.

This method returns [itself](https://metacpan.org/pod/Firefox::Marionette) to aid in chaining methods.

## mouse\_up

accepts a parameter describing which mouse button the method should apply to ([left](https://metacpan.org/pod/Firefox::Marionette::Buttons#LEFT), [middle](https://metacpan.org/pod/Firefox::Marionette::Buttons#MIDDLE) or [right](https://metacpan.org/p...

## new

accepts an optional hash as a parameter.  Allowed keys are below;

- addons - should any firefox extensions and themes be available in this session.  This defaults to "0".
- binary - use the specified path to the [Firefox](https://firefox.org/) binary, rather than the default path.
- capabilities - use the supplied [capabilities](https://metacpan.org/pod/Firefox::Marionette::Capabilities) object, for example to set whether the browser should [accept insecure certs](https://metacpan.org/pod/Firefox::Marionette::Capabilities#acce...
- chatty - Firefox is extremely chatty on the network, including checking for the latest malware/phishing sites, updates to firefox/etc.  This option is therefore off ("0") by default, however, it can be switched on ("1") if required.  Even with chat...
- console - show the [browser console](https://developer.mozilla.org/en-US/docs/Tools/Browser_Console/) when the browser is launched.  This defaults to "0" (off).  See [CONSOLE LOGGING](#console-logging) for a discussion of how to send log messages t...
- debug - should firefox's debug to be available via STDERR. This defaults to "0". Any ssh connections will also be printed to STDERR.  This defaults to "0" (off).  This setting may be updated by the [debug](#debug) method.  If this option is not a b...
- developer - only allow a [developer edition](https://www.mozilla.org/en-US/firefox/developer/) to be launched. This defaults to "0" (off).
- devtools - begin the session with the [devtools](https://developer.mozilla.org/en-US/docs/Tools) window opened in a separate window.
- geo - setup the browser [preferences](http://kb.mozillazine.org/About:config) to allow the [Geolocation API](https://developer.mozilla.org/en-US/docs/Web/API/Geolocation_API) to work.  If the value for this key is a [URI](https://metacpan.org/pod/U...
- height - set the [height](http://kb.mozillazine.org/Command_line_arguments#List_of_command_line_arguments_.28incomplete.29) of the initial firefox window
- har - begin the session with the [devtools](https://developer.mozilla.org/en-US/docs/Tools) window opened in a separate window.  The [HAR Export Trigger](https://addons.mozilla.org/en-US/firefox/addon/har-export-trigger/) addon will be loaded into ...
- host - use [ssh](https://man.openbsd.org/ssh.1) to create and automate firefox on the specified host.  See [REMOTE AUTOMATION OF FIREFOX VIA SSH](#remote-automation-of-firefox-via-ssh) and [NETWORK ARCHITECTURE](#network-architecture).  The user wi...
- implicit - a shortcut to allow directly providing the [implicit](https://metacpan.org/pod/Firefox::Marionette::Timeout#implicit) timeout, instead of needing to use timeouts from the capabilities parameter.  Overrides all longer ways.
- index - a parameter to allow the user to specify a specific firefox instance to survive and reconnect to.  It does not do anything else at the moment.  See the survive parameter.
- insecure - this is a shortcut method for setting the accept\_insecure\_certs option in the [capabilities](https://metacpan.org/pod/Firefox::Marionette::Capabilities) parameter above.
- kiosk - start the browser in [kiosk](https://support.mozilla.org/en-US/kb/firefox-enterprise-kiosk-mode) mode.
- mime\_types - any MIME types that Firefox will encounter during this session.  MIME types that are not specified will result in a hung browser (the File Download popup will appear).
- nightly - only allow a [nightly release](https://www.mozilla.org/en-US/firefox/channel/desktop/#nightly) to be launched.  This defaults to "0" (off).
- port - if the "host" parameter is also set, use [ssh](https://man.openbsd.org/ssh.1) to create and automate firefox via the specified port.  See [REMOTE AUTOMATION OF FIREFOX VIA SSH](#remote-automation-of-firefox-via-ssh) and [NETWORK ARCHITECTURE...
- page\_load - a shortcut to allow directly providing the [page\_load](https://metacpan.org/pod/Firefox::Marionette::Timeouts#page_load) timeout, instead of needing to use timeouts from the capabilities parameter.  Overrides all longer ways.
- profile - create a new profile based on the supplied [profile](https://metacpan.org/pod/Firefox::Marionette::Profile).  NOTE: firefox ignores any changes made to the profile on the disk while it is running, instead, use the [set\_pref](#set_pref) a...
- profile\_name - pick a specific existing profile to automate, rather than creating a new profile.  [Firefox](https://firefox.com) refuses to allow more than one instance of a profile to run at the same time.  Profile names can be obtained by using ...

    - the preference `security.webauth.webauthn_enable_softtoken` must be set to `true` in the profile OR
    - the `webauth` parameter to this method must be set to `0`

    NOTE: firefox ignores any changes made to the profile on the disk while it is running, instead, use the [set\_pref](#set_pref) and [clear\_pref](#clear_pref) methods to make changes while firefox is running.

- proxy - this is a shortcut method for setting a [proxy](https://metacpan.org/pod/Firefox::Marionette::Proxy) using the [capabilities](https://metacpan.org/pod/Firefox::Marionette::Capabilities) parameter above.  It accepts a proxy URL, with the fol...
- reconnect - an experimental parameter to allow a reconnection to firefox that a connection has been discontinued.  See the survive parameter.
- scp - force the scp protocol when transferring files to remote hosts via ssh. See [REMOTE AUTOMATION OF FIREFOX VIA SSH](#remote-automation-of-firefox-via-ssh) and the --scp-only option in the [ssh-auth-cmd-marionette](https://metacpan.org/pod/ssh-...
- script - a shortcut to allow directly providing the [script](https://metacpan.org/pod/Firefox::Marionette::Timeout#script) timeout, instead of needing to use timeouts from the capabilities parameter.  Overrides all longer ways.
- seer - this option is switched off "0" by default.  When it is switched on "1", it will activate the various speculative and pre-fetch options for firefox.  NOTE: that this option only works when profile\_name/profile is not specified.
- sleep\_time\_in\_ms - the amount of time (in milliseconds) that this module should sleep when unsuccessfully calling the subroutine provided to the [await](#await) or [bye](#bye) methods.  This defaults to "1" millisecond.
- stealth - stops [navigator.webdriver](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/webdriver) from being accessible by the current web page.  This is achieved by loading an [extension](https://developer.mozilla.org/en-US/docs/Mozilla/...
- survive - if this is set to a true value, firefox will not automatically exit when the object goes out of scope.  See the reconnect parameter for an experimental technique for reconnecting.
- system\_access - firefox [after version 138](https://bugzilla.mozilla.org/show_bug.cgi?id=1944565) allows disabling system access for javascript.  By default, this module will turn on system access.
- trust - give a path to a [root certificate](https://en.wikipedia.org/wiki/Root_certificate) encoded as a [PEM encoded X.509 certificate](https://datatracker.ietf.org/doc/html/rfc7468#section-5) that will be trusted for this session.
- timeouts - a shortcut to allow directly providing a [timeout](https://metacpan.org/pod/Firefox::Marionette::Timeout) object, instead of needing to use timeouts from the capabilities parameter.  Overrides the timeouts provided (if any) in the capabi...
- trackable - if this is set, profile preferences will be [set](#set_pref) to make it harder to be tracked by the [browsers fingerprint](https://en.wikipedia.org/wiki/Device_fingerprint#Browser_fingerprint) across browser restarts.  This is on by def...
- user - if the "host" parameter is also set, use [ssh](https://man.openbsd.org/ssh.1) to create and automate firefox with the specified user.  See [REMOTE AUTOMATION OF FIREFOX VIA SSH](#remote-automation-of-firefox-via-ssh) and [NETWORK ARCHITECTUR...
- via - specifies a [proxy jump box](https://man.openbsd.org/ssh_config#ProxyJump) to be used to connect to a remote host.  See the host parameter.
- visible - should firefox be visible on the desktop.  This defaults to "0".  When moving from a X11 platform to another X11 platform, you can set visible to 'local' to enable [X11 forwarding](https://man.openbsd.org/ssh#X).  See [X11 FORWARDING WITH...
- waterfox - only allow a binary that looks like a [waterfox version](https://www.waterfox.net/) to be launched.
- webauthn - a boolean parameter to determine whether or not to [add a webauthn authenticator](#add_webauthn_authenticator) after the connection is established.  The default is to add a webauthn authenticator for Firefox after version 118.
- width - set the [width](http://kb.mozillazine.org/Command_line_arguments#List_of_command_line_arguments_.28incomplete.29) of the initial firefox window

This method returns a new `Firefox::Marionette` object, connected to an instance of [firefox](https://firefox.com).  In a non MacOS/Win32/Cygwin environment, if necessary (no DISPLAY variable can be found and the visible parameter to the new method h...

    use Firefox::Marionette();

    my $remote_darwin_firefox = Firefox::Marionette->new(
                     debug => 'timestamp,nsHttp:1',
                     host => '10.1.2.3',
                     trust => '/path/to/root_ca.pem',
                     binary => '/Applications/Firefox.app/Contents/MacOS/firefox'
                                                        ); # start a temporary profile for a remote firefox and load a new CA into the temp profile
    ...

    foreach my $profile_name (Firefox::Marionette::Profile->names()) {
        my $firefox_with_existing_profile = Firefox::Marionette->new( profile_name => $profile_name, visible => 1 );
        ...
    }

## new\_window

accepts an optional hash as the parameter.  Allowed keys are below;

- focus - a boolean field representing if the new window be opened in the foreground (focused) or background (not focused). Defaults to false.
- private - a boolean field representing if the new window should be a private window. Defaults to false.
- type - the type of the new window. Can be one of 'tab' or 'window'. Defaults to 'tab'.

Returns the [window handle](https://metacpan.org/pod/Firefox::Marionette::WebWindow) for the new window.

    use Firefox::Marionette();

    my $firefox = Firefox::Marionette->new();

README.md  view on Meta::CPAN

     ---------          ----------         -----------
     | Perl  |  SSH     | SSH    |  SSH    | Firefox |
     | runs  |--------->| Jump   |-------->| runs    |
     | here  |          | Box    |         | here    |
     ---------          ----------         -----------
                                                |
     ----------          ----------             |
     | Target |  HTTPS   | Squid  |    TLS      |
     | Web    |<---------| Proxy  |<-------------
     | Site   |          | Server |
     ----------          ----------

In addition, the proxy parameter can be used to specify multiple proxies using a reference
to a list.

    my $firefox = Firefox::Marionette->new(
                    host  => 'Firefox.runs.here'
                    trust => '/path/to/ca-for-squid-proxy-server.crt',
                    proxy => [ 'https://Squid1.Proxy.Server:3128', 'https://Squid2.Proxy.Server:3128' ]
                       )->go('https://Target.Web.Site');

When firefox gets a list of proxies, it will use the first one that works.  In addition, it will perform a basic form of proxy failover, which may involve a failed network request before it fails over to the next proxy.  In the diagram below, Squid1....

                                          ----------
                                     TLS  | Squid1 |
                                   ------>| Proxy  |-----
                                   |      | Server |    |
     ---------      -----------    |      ----------    |       -----------
     | Perl  | SSH  | Firefox |    |                    | HTTPS | Target  |
     | runs  |----->| runs    |----|                    ------->| Web     |
     | here  |      | here    |    |                    |       | Site    |
     ---------      -----------    |      ----------    |       -----------
                                   | TLS  | Squid2 |    |
                                   ------>| Proxy  |-----
                                          | Server |
                                          ----------

See the [REMOTE AUTOMATION OF FIREFOX VIA SSH](#remote-automation-of-firefox-via-ssh) section for more options.

See [SETTING UP SOCKS SERVERS USING SSH](https://metacpan.org/pod/Firefox::Marionette::Proxy#SETTING-UP-SOCKS-SERVERS-USING-SSH) for easy proxying via [ssh](https://man.openbsd.org/ssh)

See [GEO LOCATION](#geo-location) section for how to combine this with providing appropriate browser settings for the end point.

# AUTOMATING THE FIREFOX PASSWORD MANAGER

This module allows you to login to a website without ever directly handling usernames and password details.  The Password Manager may be preloaded with appropriate passwords and locked, like so;

    use Firefox::Marionette();

    my $firefox = Firefox::Marionette->new( profile_name => 'locked' ); # using a pre-built profile called 'locked'
    if ($firefox->pwd_mgr_needs_login()) {
        my $new_password = IO::Prompt::prompt(-echo => q[*], 'Enter the password for the locked profile:');
        $firefox->pwd_mgr_login($password);
    } else {
        my $new_password = IO::Prompt::prompt(-echo => q[*], 'Enter the new password for the locked profile:');
        $firefox->pwd_mgr_lock($password);
    }
    ...
    $firefox->pwd_mgr_logout();

Usernames and passwords (for both HTTP Authentication popups and HTML Form based logins) may be added, viewed and deleted.

    use WebService::HIBP();

    my $hibp = WebService::HIBP->new();

    $firefox->add_login(host => 'https://github.com', user => 'me@example.org', password => 'qwerty', user_field => 'login', password_field => 'password');
    $firefox->add_login(host => 'https://pause.perl.org', user => 'AUSER', password => 'qwerty', realm => 'PAUSE');
    ...
    foreach my $login ($firefox->logins()) {
        if ($hibp->password($login->password())) { # does NOT send the password to the HIBP webservice
            warn "HIBP reports that your password for the " . $login->user() " account at " . $login->host() . " has been found in a data breach";
            $firefox->delete_login($login); # how could this possibly help?
        }
    }

And used to fill in login prompts without explicitly knowing the account details.

    $firefox->go('https://pause.perl.org/pause/authenquery')->accept_alert(); # this goes to the page and submits the http auth popup

    $firefox->go('https://github.com/login')->fill_login(); # fill the login and password fields without needing to see them

# GEO LOCATION

The firefox [Geolocation API](https://developer.mozilla.org/en-US/docs/Web/API/Geolocation_API) can be used by supplying the `geo` parameter to the [new](#new) method and then calling the [geo](#geo) method (from a [secure context](https://developer....

The [geo](#geo) method can accept various specific latitude and longitude parameters as a list, such as;

    $firefox->geo(latitude => -37.82896, longitude => 144.9811);

    OR

    $firefox->geo(lat => -37.82896, long => 144.9811);

    OR

    $firefox->geo(lat => -37.82896, lng => 144.9811);

    OR

    $firefox->geo(lat => -37.82896, lon => 144.9811);

or it can be passed in as a reference, such as;

    $firefox->geo({ latitude => -37.82896, longitude => 144.9811 });

the combination of a variety of parameter names and the ability to pass parameters in as a reference means it can be deal with various geo location websites, such as;

    $firefox->geo($firefox->json('https://freeipapi.com/api/json/')); # get geo location from current IP address

    $firefox->geo($firefox->json('https://geocode.maps.co/search?street=101+Collins+St&city=Melbourne&state=VIC&postalcode=3000&country=AU&format=json')->[0]); # get geo location of street address

    $firefox->geo($firefox->json('http://api.positionstack.com/v1/forward?access_key=' . $access_key . '&query=101+Collins+St,Melbourne,VIC+3000')->{data}->[0]); # get geo location of street address using api key

    $firefox->geo($firefox->json('https://api.ipgeolocation.io/ipgeo?apiKey=' . $api_key)); # get geo location from current IP address

    $firefox->geo($firefox->json('http://api.ipstack.com/142.250.70.206?access_key=' . $api_key)); # get geo location from specific IP address (http access only for free)

These sites were active at the time this documentation was written, but mainly function as an illustration of the flexibility of [geo](#geo) and [json](#json) methods in providing the desired location to the [Geolocation API](https://developer.mozill...

As mentioned in the [geo](#geo) method documentation, the [ipgeolocation API](https://ipgeolocation.io/documentation/ip-geolocation-api.html) is the only API that currently providing geolocation data and matching timezone data in one API call.  If th...

# CONSOLE LOGGING

Sending debug to the console can be quite confusing in firefox, as some techniques won't work in [chrome](#chrome) context.  The following example can be quite useful.

    use Firefox::Marionette();

    my $firefox = Firefox::Marionette->new( visible => 1, devtools => 1, console => 1, devtools => 1 );

    $firefox->script( q[console.log("This goes to devtools b/c it's being generated in content mode")]);

    $firefox->chrome()->script( q[console.log("Sent out on standard error for Firefox 136 and later")]);

# REMOTE AUTOMATION OF FIREFOX VIA SSH

    use Firefox::Marionette();

    my $firefox = Firefox::Marionette->new( host => 'remote.example.org', debug => 1 );



( run in 1.950 second using v1.01-cache-2.11-cpan-364913b4093 )