Provided by: libfirefox-marionette-perl_1.22-1_all bug

NAME

       Firefox::Marionette - Automate the Firefox browser with the Marionette protocol

VERSION

       Version 1.22

SYNOPSIS

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

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

           say $firefox->find_tag('title')->property('innerHTML'); # same as $firefox->title();

           say $firefox->html();

           $firefox->find_class('container-fluid')->find_id('metacpan_search-input')->type('Test::More');

           say "Height of search box is " . $firefox->find_class('container-fluid')->css('height');

           my $file_handle = $firefox->selfie();

           $firefox->find('//button[@name="lucky"]')->click();

           $firefox->await(sub { $firefox->interactive() && $firefox->find_partial('Download') })->click();

DESCRIPTION

       This is a client module to automate the Mozilla Firefox browser via the Marionette
       protocol <https://developer.mozilla.org/en-US/docs/Mozilla/QA/Marionette/Protocol>

SUBROUTINES/METHODS

   accept_alert
       accepts a currently displayed modal message box

   accept_connections
       Enables or disables accepting new socket connections.  By calling this method with false
       the server will not accept any further connections, but existing connections will not be
       forcible closed. Use true to re-enable accepting connections.

       Please note that when closing the connection via the client you can end-up in a non-
       recoverable state if it hasn't been enabled before.

   active_element
       returns the active element of the current browsing context's document element, if the
       document element is non-null.

   add_certificate
       accepts a hash as a parameter and adds the specified certificate to the Firefox database
       with the supplied or default trust.  Allowed keys are below;

       •   path - a file system path to a single PEM encoded X.509 certificate
           <https://datatracker.ietf.org/doc/html/rfc7468#section-5>.

       •   string - a string containg a single PEM encoded X.509 certificate
           <https://datatracker.ietf.org/doc/html/rfc7468#section-5>

       •   trust - This is the trustargs <https://www.mankier.com/1/certutil#-t> value for NSS
           <https://wiki.mozilla.org/NSS>.  If defaults to 'C,,';

       This method returns itself to aid in chaining methods.

           use Firefox::Marionette();

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

   add_cookie
       accepts a single cookie object as the first parameter and adds it to the current cookie
       jar.  This method returns itself to aid in chaining methods.

       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
       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 itself to aid in chaining methods.

   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/form#attr-action> default to submitting to the URL of the
           page containing the login form, so that is stored here. This field should be omitted
           (it will be set to undef) for http auth type authentications and "" means to match
           against any form action.

       •   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 blank, the hostname is used instead. For HTML form logins, this field should not
           be specified.

       •   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 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

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

           # or just directly

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

       This method returns itself 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 method

   addons
       returns if pre-existing addons (extensions/themes) are allowed to run.  This will be true
       for Firefox versions less than 55, as -safe-mode cannot be automated.

   alert_text
       Returns the message shown in a currently displayed modal message box

   alive
       This method returns true or false depending on if the Firefox process is still running.

   application_type
       returns the application type for the Marionette protocol.  Should be 'gecko'.

   async_script
       accepts a scalar containing a javascript function that is executed in the browser.  This
       method returns itself to aid in chaining methods.

       The executing javascript is subject to the script timeout, which, by default is 30
       seconds.

   attribute
       accepts an element as the first parameter and a scalar attribute name as the second
       parameter.  It returns the initial value of the attribute with the supplied name.  This
       method will return the initial content, the property method will return the current
       content.

           use Firefox::Marionette();

           my $firefox = Firefox::Marionette->new()->go('https://metacpan.org/');
           my $element = $firefox->find_id('search_input');
           !defined $element->attribute('value') or die "attribute is not defined!");
           $element->type('Test::More');
           !defined $element->attribute('value') or die "attribute is still not defined!");

   await
       accepts a subroutine reference as a parameter and then executes the subroutine.  If a not
       found exception is thrown, this method will sleep for sleep_time_in_ms milliseconds and
       then execute the subroutine again.  When the subroutine executes successfully, it will
       return what the subroutine returns.

           use Firefox::Marionette();

           my $firefox = Firefox::Marionette->new(sleep_time_in_ms => 5)->go('https://metacpan.org/');

           $firefox->find_id('metacpan_search-input')->type('Test::More');

           $firefox->find_name('lucky')->click();

           $firefox->await(sub { $firefox->interactive() && $firefox->find_partial('Download') })->click();

   back
       causes the browser to traverse one step backward in the joint history of the current
       browsing context.  The browser will wait for the one step backward to complete or the
       session's page_load duration to elapse before returning, which, by default is 5 minutes.
       This method returns itself to aid in chaining methods.

   debug
       accept a boolean and return the current value of the debug setting.  This allows the
       dynamic setting of debug.

   default_binary_name
       just returns the string 'firefox'.  Only of interest when sub-classing.

   browser_version
       This method returns the current version of firefox.

   bye
       accepts a subroutine reference as a parameter and then executes the subroutine.  If the
       subroutine executes successfully, this method will sleep for sleep_time_in_ms milliseconds
       and then execute the subroutine again.  When a not found exception is thrown, this method
       will return itself to aid in chaining methods.

           use Firefox::Marionette();

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

           $firefox->find_id('metacpan_search-input')->type('Test::More');

           $firefox->find_name('lucky')->click();

           $firefox->bye(sub { $firefox->find_name('lucky') })->await(sub { $firefox->interactive() && $firefox->find_partial('Download') })->click();

   capabilities
       returns the capabilities of the current firefox binary.  You can retrieve timeouts or a
       proxy with this method.

   certificate_as_pem
       accepts a certificate stored in the Firefox database as a parameter and returns a PEM
       encoded X.509 certificate <https://datatracker.ietf.org/doc/html/rfc7468#section-5> as a
       string.

           use Firefox::Marionette();

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

           # Generating a ca-bundle.crt to STDOUT from the current firefox instance

           foreach my $certificate (sort { $a->display_name() cmp $b->display_name } $firefox->certificates()) {
               if ($certificate->is_ca_cert()) {
                   print '# ' . $certificate->display_name() . "\n" . $firefox->certificate_as_pem($certificate) . "\n";
               }
           }

       The ca-bundle-for-firefox command that is provided as part of this distribution does this.

   certificates
       returns a list of all known certificates in the Firefox database.

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

           # Sometimes firefox can neglect old certificates.  See https://bugzilla.mozilla.org/show_bug.cgi?id=1710716

           my $firefox = Firefox::Marionette->new();
           foreach my $certificate (grep { $_->is_ca_cert() && $_->not_valid_after() < time } $firefox->certificates()) {
               say "The " . $certificate->display_name() " . certificate has expired and should be removed";
           }

       This method returns itself to aid in chaining methods.

   child_error
       This method returns the $? (CHILD_ERROR) for the Firefox process, or undefined if the
       process has not yet exited.

   chrome
       changes the scope of subsequent commands to chrome context.  This allows things like
       interacting with firefox menu's and buttons outside of the browser window.

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

           my $firefox = Firefox::Marionette->new()->chrome();
           $firefox->script(...); # running script in chrome context
           $firefox->content();

       See the context method for an alternative methods for changing the context.

   chrome_window_handle
       returns an server-assigned integer identifiers for the current chrome window that uniquely
       identifies it within this Marionette instance.  This can be used to switch to this window
       at a later point. This corresponds to a window that may itself contain tabs.  This method
       is replaced by window_handle and appropriate context calls for Firefox 94 and after
       <https://developer.mozilla.org/en-
       US/docs/Mozilla/Firefox/Releases/94#webdriver_conformance_marionette>.

   chrome_window_handles
       returns identifiers for each open chrome window for tests interested in managing a set of
       chrome windows and tabs separately.  This method is replaced by window_handles and
       appropriate context calls for Firefox 94 and after <https://developer.mozilla.org/en-
       US/docs/Mozilla/Firefox/Releases/94#webdriver_conformance_marionette>.

   clear
       accepts a element as the first parameter and clears any user supplied input

   click
       accepts a element as the first parameter and sends a 'click' to it.  The browser will wait
       for any page load to complete or the session's page_load duration to elapse before
       returning, which, by default is 5 minutes.  The click method is also used to choose an
       option in a select dropdown.

           use Firefox::Marionette();

           my $firefox = Firefox::Marionette->new(visible => 1)->go('https://ebay.com');
           my $select = $firefox->find_tag('select');
           foreach my $option ($select->find_tag('option')) {
               if ($option->property('value') == 58058) { # Computers/Tablets & Networking
                   $option->click();
               }
           }

   close_current_chrome_window_handle
       closes the current chrome window (that is the entire window, not just the tabs).  It
       returns a list of still available chrome window handles. You will need to switch_to_window
       to use another window.

   close_current_window_handle
       closes the current window/tab.  It returns a list of still available window/tab handles.

   content
       changes the scope of subsequent commands to browsing context.  This is the default for
       when firefox starts and restricts commands to operating in the browser window only.

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

           my $firefox = Firefox::Marionette->new()->chrome();
           $firefox->script(...); # running script in chrome context
           $firefox->content();

       See the context method for an alternative methods for changing the context.

   context
       accepts a string as the first parameter, which may be either 'content' or 'chrome'.  It
       returns the context type that is Marionette's current target for browsing context scoped
       commands.

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

           my $firefox = Firefox::Marionette->new();
           if ($firefox->context() eq 'content') {
              say "I knew that was going to happen";
           }
           my $old_context = $firefox->context('chrome');
           $firefox->script(...); # running script in chrome context
           $firefox->context($old_context);

       See the content and chrome methods for alternative methods for changing the context.

   cookies
       returns the contents of the cookie jar in scalar or list context.

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

           my $firefox = Firefox::Marionette->new()->go('https://github.com');
           foreach my $cookie ($firefox->cookies()) {
               if (defined $cookie->same_site()) {
                   say "Cookie " . $cookie->name() . " has a SameSite of " . $cookie->same_site();
               } else {
                   warn "Cookie " . $cookie->name() . " does not have the SameSite attribute defined";
               }
           }

   css
       accepts an element as the first parameter and a scalar CSS property name as the second
       parameter.  It returns the value of the computed style for that property.

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

           my $firefox = Firefox::Marionette->new()->go('https://metacpan.org/');
           say $firefox->find_id('metacpan_search-input')->css('height');

   current_chrome_window_handle
       see chrome_window_handle.

   delete_certificate
       accepts a certificate stored in the Firefox database as a parameter and deletes/distrusts
       the certificate from the Firefox database.

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

           my $firefox = Firefox::Marionette->new();
           foreach my $certificate ($firefox->certificates()) {
               if ($certificate->is_ca_cert()) {
                   $firefox->delete_certificate($certificate);
               } else {
                   say "This " . $certificate->display_name() " certificate is NOT a certificate authority, therefore it is not being deleted";
               }
           }
           say "Good luck visiting a HTTPS website!";

       This method returns itself to aid in chaining methods.

   delete_cookie
       deletes a single cookie by name.  Accepts a scalar containing the cookie name as a
       parameter.  This method returns itself to aid in chaining methods.

           use Firefox::Marionette();

           my $firefox = Firefox::Marionette->new()->go('https://github.com');
           foreach my $cookie ($firefox->cookies()) {
               warn "Cookie " . $cookie->name() . " is being deleted";
               $firefox->delete_cookie($cookie->name());
           }
           foreach my $cookie ($firefox->cookies()) {
               die "Should be no cookies here now";
           }

   delete_cookies
       here be cookie monsters! This method returns itself to aid in chaining methods.

   delete_header
       accepts a list of HTTP header names to delete from future HTTP Requests.

           use Firefox::Marionette();

           my $firefox = Firefox::Marionette->new();
           $firefox->delete_header( 'User-Agent', 'Accept', 'Accept-Encoding' );

       will remove the User-Agent <https://developer.mozilla.org/en-
       US/docs/Web/HTTP/Headers/User-Agent>, Accept <https://developer.mozilla.org/en-
       US/docs/Web/HTTP/Headers/Accept> and Accept-Encoding <https://developer.mozilla.org/en-
       US/docs/Web/HTTP/Headers/Accept-Encoding> headers from all future requests

       This method returns itself to aid in chaining methods.

   delete_login
       accepts a login as a parameter.

           use Firefox::Marionette();

           my $firefox = Firefox::Marionette->new();
           foreach my $login ($firefox->logins()) {
               if ($login->user() eq 'me@example.org') {
                   $firefox->delete_login($login);
               }
           }

       will remove the logins with the username matching 'me@example.org'.

       This method returns itself to aid in chaining methods.

   delete_logins
       This method empties the password database.

           use Firefox::Marionette();

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

       This method returns itself to aid in chaining methods.

   delete_session
       deletes the current WebDriver session.

   delete_site_header
       accepts a host name and a list of HTTP headers names to delete from future HTTP Requests.

           use Firefox::Marionette();

           my $firefox = Firefox::Marionette->new();
           $firefox->delete_header( 'metacpan.org', 'User-Agent', 'Accept', 'Accept-Encoding' );

       will remove the User-Agent <https://developer.mozilla.org/en-
       US/docs/Web/HTTP/Headers/User-Agent>, Accept <https://developer.mozilla.org/en-
       US/docs/Web/HTTP/Headers/Accept> and Accept-Encoding <https://developer.mozilla.org/en-
       US/docs/Web/HTTP/Headers/Accept-Encoding> headers from all future requests to
       metacpan.org.

       This method returns itself to aid in chaining methods.

   developer
       returns true if the current version of firefox is a developer edition
       <https://www.mozilla.org/en-US/firefox/developer/> (does the minor version number end with
       an 'b\d+'?) version.

   dismiss_alert
       dismisses a currently displayed modal message box

   download
       accepts a filesystem path and returns a matching filehandle.  This is trivial for locally
       running firefox, but sufficiently complex to justify the method for a remote firefox
       running over ssh.

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

           my $firefox = Firefox::Marionette->new( host => '10.1.2.3' )->go('https://metacpan.org/');

           $firefox->find_class('container-fluid')->find_id('metacpan_search-input')->type('Test::More');

           $firefox->find('//button[@name="lucky"]')->click();

           $firefox->await(sub { $firefox->interactive() && $firefox->find_partial('Download') })->click();

           while(!$firefox->downloads()) { sleep 1 }

           foreach my $path ($firefox->downloads()) {

               my $handle = $firefox->download($path);

               # do something with downloaded file handle

           }

   downloading
       returns true if any files in downloads end in ".part"

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

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

           $firefox->find_class('container-fluid')->find_id('metacpan_search-input')->type('Test::More');

           $firefox->find('//button[@name="lucky"]')->click();

           $firefox->await(sub { $firefox->interactive() && $firefox->find_partial('Download') })->click();

           while(!$firefox->downloads()) { sleep 1 }

           while($firefox->downloading()) { sleep 1 }

           foreach my $path ($firefox->downloads()) {
               say $path;
           }

   downloads
       returns a list of file paths (including partial downloads) of downloads during this
       Firefox session.

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

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

           $firefox->find_class('container-fluid')->find_id('metacpan_search-input')->type('Test::More');

           $firefox->find('//button[@name="lucky"]')->click();

           $firefox->await(sub { $firefox->interactive() && $firefox->find_partial('Download') })->click();

           while(!$firefox->downloads()) { sleep 1 }

           foreach my $path ($firefox->downloads()) {
               say $path;
           }

   error_message
       This method returns a human readable error message describing how the Firefox process
       exited (assuming it started okay).  On Win32 platforms this information is restricted to
       exit code.

   execute
       This utility method executes a command with arguments and returns STDOUT as a chomped
       string.  It is a simple method only intended for the Firefox::Marionette::* modules.

   fill_login
       This method searchs the Password Manager <https://support.mozilla.org/en-US/kb/password-
       manager-remember-delete-edit-logins> for an appropriate login for any form on the current
       page.  The form must match the host, the action attribute and the user and password field
       names.

           use Firefox::Marionette();
           use IO::Prompt();

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

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

           my $url = 'https://github.com';

           my $user = 'me@example.org';

           my $password = IO::Prompt::prompt(-echo => q[*], "Please enter the password for the $user account when logging into $url:");

           $firefox->add_login(host => $url, user => $user, password => 'qwerty', user_field => 'login', password_field => 'password');

           $firefox->go("$url/login");

           $firefox->fill_login();

   find
       accepts an xpath expression <https://en.wikipedia.org/wiki/XPath> as the first parameter
       and returns the first element that matches this expression.

       This method is subject to the implicit timeout, which, by default is 0 seconds.

           use Firefox::Marionette();

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

           $firefox->find('//input[@id="metacpan_search-input"]')->type('Test::More');

           # OR in list context

           foreach my $element ($firefox->find('//input[@id="metacpan_search-input"]')) {
               $element->type('Test::More');
           }

       If no elements are found, a not found exception will be thrown.  For the same
       functionality that returns undef if no elements are found, see the has method.

   find_id
       accepts an id <https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/id> as
       the first parameter and returns the first element with a matching 'id' property.

       This method is subject to the implicit timeout, which, by default is 0 seconds.

           use Firefox::Marionette();

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

           $firefox->find_id('metacpan_search-input')->type('Test::More');

           # OR in list context

           foreach my $element ($firefox->find_id('metacpan_search-input')) {
               $element->type('Test::More');
           }

       If no elements are found, a not found exception will be thrown.  For the same
       functionality that returns undef if no elements are found, see the has_id method.

   find_name
       This method returns the first element with a matching 'name' property.

       This method is subject to the implicit timeout, which, by default is 0 seconds.

           use Firefox::Marionette();

           my $firefox = Firefox::Marionette->new()->go('https://metacpan.org/');
           $firefox->find_name('q')->type('Test::More');

           # OR in list context

           foreach my $element ($firefox->find_name('q')) {
               $element->type('Test::More');
           }

       If no elements are found, a not found exception will be thrown.  For the same
       functionality that returns undef if no elements are found, see the has_name method.

   find_class
       accepts a class name <https://developer.mozilla.org/en-
       US/docs/Web/HTML/Global_attributes/class> as the first parameter and returns the first
       element with a matching 'class' property.

       This method is subject to the implicit timeout, which, by default is 0 seconds.

           use Firefox::Marionette();

           my $firefox = Firefox::Marionette->new()->go('https://metacpan.org/');
           $firefox->find_class('form-control home-metacpan_search-input')->type('Test::More');

           # OR in list context

           foreach my $element ($firefox->find_class('form-control home-metacpan_search-input')) {
               $element->type('Test::More');
           }

       If no elements are found, a not found exception will be thrown.  For the same
       functionality that returns undef if no elements are found, see the has_class method.

   find_selector
       accepts a CSS Selector <https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors> as
       the first parameter and returns the first element that matches that selector.

       This method is subject to the implicit timeout, which, by default is 0 seconds.

           use Firefox::Marionette();

           my $firefox = Firefox::Marionette->new()->go('https://metacpan.org/');
           $firefox->find_selector('input.home-metacpan_search-input')->type('Test::More');

           # OR in list context

           foreach my $element ($firefox->find_selector('input.home-metacpan_search-input')) {
               $element->type('Test::More');
           }

       If no elements are found, a not found exception will be thrown.  For the same
       functionality that returns undef if no elements are found, see the has_selector method.

   find_tag
       accepts a tag name <https://developer.mozilla.org/en-US/docs/Web/API/Element/tagName> as
       the first parameter and returns the first element with this tag name.

       This method is subject to the implicit timeout, which, by default is 0 seconds.

           use Firefox::Marionette();

           my $firefox = Firefox::Marionette->new()->go('https://metacpan.org/');
           my $element = $firefox->find_tag('input');

           # OR in list context

           foreach my $element ($firefox->find_tag('input')) {
               # do something
           }

       If no elements are found, a not found exception will be thrown. For the same functionality
       that returns undef if no elements are found, see the has_tag method.

   find_link
       accepts a text string as the first parameter and returns the first link element that has a
       matching link text.

       This method is subject to the implicit timeout, which, by default is 0 seconds.

           use Firefox::Marionette();

           my $firefox = Firefox::Marionette->new()->go('https://metacpan.org/');
           $firefox->find_link('API')->click();

           # OR in list context

           foreach my $element ($firefox->find_link('API')) {
               $element->click();
           }

       If no elements are found, a not found exception will be thrown.  For the same
       functionality that returns undef if no elements are found, see the has_link method.

   find_partial
       accepts a text string as the first parameter and returns the first link element that has a
       partially matching link text.

       This method is subject to the implicit timeout, which, by default is 0 seconds.

           use Firefox::Marionette();

           my $firefox = Firefox::Marionette->new()->go('https://metacpan.org/');
           $firefox->find_partial('AP')->click();

           # OR in list context

           foreach my $element ($firefox->find_partial('AP')) {
               $element->click();
           }

       If no elements are found, a not found exception will be thrown.  For the same
       functionality that returns undef if no elements are found, see the has_partial method.

   forward
       causes the browser to traverse one step forward in the joint history of the current
       browsing context. The browser will wait for the one step forward to complete or the
       session's page_load duration to elapse before returning, which, by default is 5 minutes.
       This method returns itself to aid in chaining methods.

   full_screen
       full screens the firefox window. This method returns itself to aid in chaining methods.

   go
       Navigates the current browsing context to the given URI and waits for the document to load
       or the session's page_load duration to elapse before returning, which, by default is 5
       minutes.

           use Firefox::Marionette();

           my $firefox = Firefox::Marionette->new();
           $firefox->go('https://metacpan.org/'); # will only return when metacpan.org is FULLY loaded (including all images / js / css)

       To make the go method return quicker, you need to set the page load strategy capability to
       an appropriate value, such as below;

           use Firefox::Marionette();

           my $firefox = Firefox::Marionette->new( capabilities => Firefox::Marionette::Capabilities->new( page_load_strategy => 'eager' ));
           $firefox->go('https://metacpan.org/'); # will return once the main document has been loaded and parsed, but BEFORE sub-resources (images/stylesheets/frames) have been loaded.

       When going directly to a URL that needs to be downloaded, please see BUGS AND LIMITATIONS
       for a necessary workaround.

       This method returns itself to aid in chaining methods.

   har
       returns a hashref representing the http archive
       <https://en.wikipedia.org/wiki/HAR_(file_format)> of the session.  This function is
       subject to the script timeout, which, by default is 30 seconds.  It is also possible for
       the function to hang (until the script timeout) if the original devtools
       <https://developer.mozilla.org/en-US/docs/Tools> window is closed.  The hashref has been
       designed to be accepted by the Archive::Har module.  This function should be considered
       experimental.  Feedback welcome.

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

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

           $firefox->go("http://metacpan.org/");

           $firefox->find('//input[@id="metacpan_search-input"]')->type('Test::More');
           $firefox->find_name('lucky')->click();

           my $har = Archive::Har->new();
           $har->hashref($firefox->har());

           foreach my $entry ($har->entries()) {
               say $entry->request()->url() . " spent " . $entry->timings()->connect() . " ms establishing a TCP connection";
           }

   has
       accepts an xpath expression <https://en.wikipedia.org/wiki/XPath> as the first parameter
       and returns the first element that matches this expression.

       This method is subject to the implicit timeout, which, by default is 0 seconds.

           use Firefox::Marionette();

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

           if (my $element = $firefox->has('//input[@id="metacpan_search-input"]')) {
               $element->type('Test::More');
           }

       If no elements are found, this method will return undef.  For the same functionality that
       throws a not found exception, see the find method.

   has_id
       accepts an id <https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/id> as
       the first parameter and returns the first element with a matching 'id' property.

       This method is subject to the implicit timeout, which, by default is 0 seconds.

           use Firefox::Marionette();

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

           if (my $element = $firefox->has_id('metacpan_search-input')) {
               $element->type('Test::More');
           }

       If no elements are found, this method will return undef.  For the same functionality that
       throws a not found exception, see the find_id method.

   has_name
       This method returns the first element with a matching 'name' property.

       This method is subject to the implicit timeout, which, by default is 0 seconds.

           use Firefox::Marionette();

           my $firefox = Firefox::Marionette->new()->go('https://metacpan.org/');
           if (my $element = $firefox->has_name('q')) {
               $element->type('Test::More');
           }

       If no elements are found, this method will return undef.  For the same functionality that
       throws a not found exception, see the find_name method.

   has_class
       accepts a class name <https://developer.mozilla.org/en-
       US/docs/Web/HTML/Global_attributes/class> as the first parameter and returns the first
       element with a matching 'class' property.

       This method is subject to the implicit timeout, which, by default is 0 seconds.

           use Firefox::Marionette();

           my $firefox = Firefox::Marionette->new()->go('https://metacpan.org/');
           if (my $element = $firefox->has_class('form-control home-metacpan_search-input')) {
               $element->type('Test::More');
           }

       If no elements are found, this method will return undef.  For the same functionality that
       throws a not found exception, see the find_class method.

   has_selector
       accepts a CSS Selector <https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors> as
       the first parameter and returns the first element that matches that selector.

       This method is subject to the implicit timeout, which, by default is 0 seconds.

           use Firefox::Marionette();

           my $firefox = Firefox::Marionette->new()->go('https://metacpan.org/');
           if (my $element = $firefox->has_selector('input.home-metacpan_search-input')) {
               $element->type('Test::More');
           }

       If no elements are found, this method will return undef.  For the same functionality that
       throws a not found exception, see the find_selector method.

   has_tag
       accepts a tag name <https://developer.mozilla.org/en-US/docs/Web/API/Element/tagName> as
       the first parameter and returns the first element with this tag name.

       This method is subject to the implicit timeout, which, by default is 0 seconds.

           use Firefox::Marionette();

           my $firefox = Firefox::Marionette->new()->go('https://metacpan.org/');
           if (my $element = $firefox->has_tag('input')) {
               # do something
           }

       If no elements are found, this method will return undef.  For the same functionality that
       throws a not found exception, see the find_tag method.

   has_link
       accepts a text string as the first parameter and returns the first link element that has a
       matching link text.

       This method is subject to the implicit timeout, which, by default is 0 seconds.

           use Firefox::Marionette();

           my $firefox = Firefox::Marionette->new()->go('https://metacpan.org/');
           if (my $element = $firefox->has_link('API')) {
               $element->click();
           }

       If no elements are found, this method will return undef.  For the same functionality that
       throws a not found exception, see the find_link method.

   has_partial
       accepts a text string as the first parameter and returns the first link element that has a
       partially matching link text.

       This method is subject to the implicit timeout, which, by default is 0 seconds.

           use Firefox::Marionette();

           my $firefox = Firefox::Marionette->new()->go('https://metacpan.org/');
           if (my $element = $firefox->find_partial('AP')) {
               $element->click();
           }

       If no elements are found, this method will return undef.  For the same functionality that
       throws a not found exception, see the find_partial method.

   html
       returns the page source of the content document.  This page source can be wrapped in html
       that firefox provides.  See the json method for an alternative when dealing with response
       content types such as application/json and strip for an alterative when dealing with other
       non-html content types such as text/plain.

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

           say Firefox::Marionette->new()->go('https://metacpan.org/')->html();

   images
       returns a list of all of the following elements;

       •   img <https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img>

       •   image inputs <https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/image>

       as Firefox::Marionette::Image objects.

       This method is subject to the implicit timeout, which, by default is 0 seconds.

           use Firefox::Marionette();

           my $firefox = Firefox::Marionette->new()->go('https://metacpan.org/');
           if (my $link = $firefox->images()) {
               say "Found a image with width " . $image->width() . "px and height " . $image->height() . "px from " . $image->URL();
           }

       If no elements are found, this method will return undef.

   install
       accepts the following as the first parameter;

       •   path to an xpi file <https://developer.mozilla.org/en-US/docs/Mozilla/XPI>.

       •   path to a directory containing firefox extension source code
           <https://developer.mozilla.org/en-US/docs/Mozilla/Add-
           ons/WebExtensions/Your_first_WebExtension>.  This directory will be packaged up as an
           unsigned xpi file.

       •   path to a top level file (such as manifest.json <https://developer.mozilla.org/en-
           US/docs/Mozilla/Add-ons/WebExtensions/Anatomy_of_a_WebExtension#manifest.json>) in a
           directory containing firefox extension source code <https://developer.mozilla.org/en-
           US/docs/Mozilla/Add-ons/WebExtensions/Your_first_WebExtension>.  This directory will
           be packaged up as an unsigned xpi file.

       and an optional true/false second parameter to indicate if the xpi file should be a
       temporary extension <https://extensionworkshop.com/documentation/develop/temporary-
       installation-in-firefox/> (just for the existance of this browser instance).  Unsigned xpi
       files may only be loaded temporarily <https://wiki.mozilla.org/Add-ons/Extension_Signing>
       (except for nightly firefox installations <https://www.mozilla.org/en-
       US/firefox/channel/desktop/#nightly>).  It returns the GUID for the addon which may be
       used as a parameter to the uninstall method.

           use Firefox::Marionette();

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

           my $extension_id = $firefox->install('/full/path/to/gnu_terry_pratchett-0.4-an+fx.xpi');

           # OR downloading and installing source code

           system { 'git' } 'git', 'clone', 'https://github.com/kkapsner/CanvasBlocker.git';

           if ($firefox->nightly()) {

               $extension_id = $firefox->install('./CanvasBlocker'); # permanent install for unsigned packages in nightly firefox

           } else {

               $extension_id = $firefox->install('./CanvasBlocker', 1); # temp install for normal firefox

           }

   interactive
       returns true if "document.readyState === "interactive"" or if loaded is true

           use Firefox::Marionette();

           my $firefox = Firefox::Marionette->new()->go('https://metacpan.org/');
           $firefox->find_id('search_input')->type('Type::More');
           $firefox->find('//button[@name="lucky"]')->click();
           while(!$firefox->interactive()) {
               # redirecting to Test::More page
           }

   is_displayed
       accepts an element as the first parameter.  This method returns true or false depending on
       if the element is displayed <https://firefox-source-
       docs.mozilla.org/testing/marionette/internals/interaction.html#interaction.isElementDisplayed>.

   is_enabled
       accepts an element as the first parameter.  This method returns true or false depending on
       if the element is enabled <https://w3c.github.io/webdriver/#is-element-enabled>.

   is_selected
       accepts an element as the first parameter.  This method returns true or false depending on
       if the element is selected <https://w3c.github.io/webdriver/#dfn-is-element-selected>.
       Note that this method only makes sense for checkbox <https://developer.mozilla.org/en-
       US/docs/Web/HTML/Element/input/checkbox> or radio <https://developer.mozilla.org/en-
       US/docs/Web/HTML/Element/input/radio> inputs or option <https://developer.mozilla.org/en-
       US/docs/Web/HTML/Element/option> elements in a select <https://developer.mozilla.org/en-
       US/docs/Web/HTML/Element/select> dropdown.

   json
       returns a JSON object that has been parsed from the page source of the content document.
       This is a convenience method that wraps the strip method.

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

           say Firefox::Marionette->new()->go('https://fastapi.metacpan.org/v1/download_url/Firefox::Marionette")->json()->{version};

   key_down
       accepts a parameter describing a key and returns an action for use in the perform method
       that corresponding with that key being depressed.

           use Firefox::Marionette();
           use Firefox::Marionette::Keys qw(:all);

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

           $firefox->chrome()->perform(
                                        $firefox->key_down(CONTROL()),
                                        $firefox->key_down('l'),
                                      )->release()->content();

   key_up
       accepts a parameter describing a key and returns an action for use in the perform method
       that corresponding with that key being released.

           use Firefox::Marionette();
           use Firefox::Marionette::Keys qw(:all);

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

           $firefox->chrome()->perform(
                                        $firefox->key_down(CONTROL()),
                                        $firefox->key_down('l'),
                                        $firefox->pause(20),
                                        $firefox->key_up('l'),
                                        $firefox->key_up(CONTROL())
                                      )->content();

   loaded
       returns true if "document.readyState === "complete""

           use Firefox::Marionette();

           my $firefox = Firefox::Marionette->new()->go('https://metacpan.org/');
           $firefox->find_id('search_input')->type('Type::More');
           $firefox->find('//button[@name="lucky"]')->click();
           while(!$firefox->loaded()) {
               # redirecting to Test::More page
           }

   logins_from_csv
       accepts a filehandle as a parameter and then reads the filehandle for exported logins as
       CSV.  This is known to work with the following formats;

       •   Bitwarden CSV <https://bitwarden.com/help/article/condition-bitwarden-import/>

       •   LastPass CSV <https://support.logmeininc.com/lastpass/help/how-do-i-nbsp-export-
           stored-data-from-lastpass-using-a-generic-csv-file>

       •   KeePass CSV <https://keepass.info/help/base/importexport.html#csv>

       returns a list of Firefox::Marionette::Login objects.

           use Firefox::Marionette();
           use FileHandle();

           my $handle = FileHandle->new('/path/to/last_pass.csv');
           my $firefox = Firefox::Marionette->new();
           foreach my $login (Firefox::Marionette->logins_from_csv($handle)) {
               $firefox->add_login($login);
           }

   logins_from_zip
       accepts a filehandle as a parameter and then reads the filehandle for exported logins as a
       zip file.  This is known to work with the following formats;

       •   1Password Unencrypted Export format <https://support.1password.com/1pux-format/>

       returns a list of Firefox::Marionette::Login objects.

           use Firefox::Marionette();
           use FileHandle();

           my $handle = FileHandle->new('/path/to/1Passwordv8.1pux');
           my $firefox = Firefox::Marionette->new();
           foreach my $login (Firefox::Marionette->logins_from_zip($handle)) {
               $firefox->add_login($login);
           }

   links
       returns a list of all of the following elements;

       •   anchor <https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a>

       •   area <https://developer.mozilla.org/en-US/docs/Web/HTML/Element/area>

       •   frame <https://developer.mozilla.org/en-US/docs/Web/HTML/Element/frame>

       •   iframe <https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe>

       •   meta <https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta>

       as Firefox::Marionette::Link objects.

       This method is subject to the implicit timeout, which, by default is 0 seconds.

           use Firefox::Marionette();

           my $firefox = Firefox::Marionette->new()->go('https://metacpan.org/');
           if (my $link = $firefox->links()) {
               if ($link->tag() eq 'a') {
                   warn "Found a hyperlink to " . $link->URL();
               }
           }

       If no elements are found, this method will return undef.

   macos_binary_paths
       returns a list of filesystem paths that this module will check for binaries that it can
       automate when running on MacOS <https://en.wikipedia.org/wiki/MacOS>.  Only of interest
       when sub-classing.

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

   maximise
       maximises the firefox window. This method returns itself 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 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 to aid in chaining methods.

   mouse_down
       accepts a parameter describing which mouse button the method should apply to (left, middle
       or right) and returns an action for use in the perform method that corresponding with a
       mouse button being depressed.

   mouse_move
       accepts a 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 method
       that corresponding with such a mouse movement, either to the specified co-ordinates or to
       the middle of the supplied element parameter.  Other parameters that may be passed are
       listed below;

       •   origin - the origin of the C(<x => 0, y => 0)> co-ordinates.  Should be either
           "viewport", "pointer" or an element.

       •   duration - Number of milliseconds over which to distribute the move. If not defined,
           the duration defaults to 0.

       This method returns itself to aid in chaining methods.

   mouse_up
       accepts a parameter describing which mouse button the method should apply to (left, middle
       or right) and returns an action for use in the perform method that corresponding with a
       mouse button being released.

   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 object, for example to set whether the
           browser should accept insecure certs or whether the browser should use a proxy.

       •   chatty - Firefox is extremely chatty on the network, including checking for the
           lastest 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 chatty
           switched off, connections to firefox.settings.services.mozilla.com will still be made
           <https://bugzilla.mozilla.org/show_bug.cgi?id=1598562#c13>.  The only way to prevent
           this seems to be to set firefox.settings.services.mozilla.com to 127.0.0.1 via
           /etc/hosts <https://en.wikipedia.org/wiki//etc/hosts>.  NOTE: that this option only
           works when profile_name/profile is not specified.

       •   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).

       •   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 method.

       •   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.

       •   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 the new session automatically, which means that -safe-mode will not be
           activated for this session AND this functionality will only be available for Firefox
           61+.

       •   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.

       •   implicit - a shortcut to allow directly providing the implicit timeout, instead of
           needing to use timeouts from the capabilities parameter.  Overrides all longer ways.

       •   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.

       •   page_load - a shortcut to allow directly providing the 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.  NOTE: firefox ignores
           any changes made to the profile on the disk while it is running.

       •   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
           Firefox::Marionette::Profile::names() method.  NOTE: firefox ignores any changes made
           to the profile on the disk while it is running.

       •   reconnect - an experimental parameter to allow a reconnection to firefox that a
           connection has been discontinued.  See the survive parameter.

       •   script - a shortcut to allow directly providing the 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 or bye methods.  This
           defaults to "1" millisecond.

       •   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.

       •   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 object, instead of needing
           to use timeouts from the capabilities parameter.  Overrides the timeouts provided (if
           any) in the capabilities parameter.

       •   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.  The user will default to the current user name.

       •   visible - should firefox be visible on the desktop.  This defaults to "0".

       •   waterfox - only allow a binary that looks like a waterfox version
           <https://www.waterfox.net/> to be launched.

       •   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 has been set to
       true) and possible (Xvfb can be executed successfully), this method will also
       automatically start an Xvfb <https://en.wikipedia.org/wiki/Xvfb> instance.

           use Firefox::Marionette();

           my $remote_darwin_firefox = Firefox::Marionette->new(
                            debug => 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 for the new window.

           use Firefox::Marionette();

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

           my $window_handle = $firefox->new_window(type => 'tab');

           $firefox->switch_to_window($window_handle);

   new_session
       creates a new WebDriver session.  It is expected that the caller performs the necessary
       checks on the requested capabilities to be WebDriver conforming.  The WebDriver service
       offered by Marionette does not match or negotiate capabilities beyond type and bounds
       checks.

   nightly
       returns true if the current version of firefox is a nightly release
       <https://www.mozilla.org/en-US/firefox/channel/desktop/#nightly> (does the minor version
       number end with an 'a1'?)

   paper_sizes
       returns a list of all the recognised names for paper sizes, such as A4 or LEGAL.

   pause
       accepts a parameter in milliseconds and returns a corresponding action for the perform
       method that will cause a pause in the chain of actions given to the perform method.

   pdf
       accepts a optional hash as the first parameter with the following allowed keys;

       •   landscape - Paper orientation.  Boolean value.  Defaults to false

       •   margin - A hash describing the margins.  The hash may have the following optional
           keys, 'top', 'left', 'right' and 'bottom'.  All these keys are in cm and default to 1
           (~0.4 inches)

       •   page - A hash describing the page.  The hash may have the following keys; 'height' and
           'width'.  Both keys are in cm and default to US letter size.  See the 'size' key.

       •   page_ranges - A list of the pages to print. Available for Firefox 96
           <https://developer.mozilla.org/en-
           US/docs/Mozilla/Firefox/Releases/96#webdriver_conformance_marionette> and after.

       •   print_background - Print background graphics.  Boolean value.  Defaults to false.

       •   raw - rather than a file handle containing the PDF, the binary PDF will be returned.

       •   scale - Scale of the webpage rendering.  Defaults to 1.

       •   size - The desired size (width and height) of the pdf, specified by name.  See the
           page key for an alternative and the paper_sizes method for a list of accepted page
           size names.

       •   shrink_to_fit - Whether or not to override page size as defined by CSS.  Boolean
           value.  Defaults to true.

       returns a File::Temp object containing a PDF encoded version of the current page for
       printing.

           use Firefox::Marionette();

           my $firefox = Firefox::Marionette->new()->go('https://metacpan.org/');
           my $handle = $firefox->pdf();
           foreach my $paper_size ($firefox->paper_sizes()) {
                   $handle = $firefox->pdf(size => $paper_size, landscape => 1, margin => { top => 0.5, left => 1.5 });
                   ...
                   print $firefox->pdf(page => { width => 21, height => 27 }, raw => 1);
                   ...
           }

   perform
       accepts a list of actions (see mouse_up, mouse_down, mouse_move, pause, key_down and
       key_up) and performs these actions in sequence.  This allows fine control over
       interactions, including sending right clicks to the browser and sending Control, Alt and
       other special keys.  The release method will complete outstanding actions (such as
       mouse_up or key_up actions).

           use Firefox::Marionette();
           use Firefox::Marionette::Keys qw(:all);
           use Firefox::Marionette::Buttons qw(:all);

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

           $firefox->chrome()->perform(
                                        $firefox->key_down(CONTROL()),
                                        $firefox->key_down('l'),
                                        $firefox->key_up('l'),
                                        $firefox->key_up(CONTROL())
                                      )->content();

           $firefox->go('https://metacpan.org');
           my $help_button = $firefox->find_class('btn search-btn help-btn');
           $firefox->perform(
                                         $firefox->mouse_move($help_button),
                                         $firefox->mouse_down(RIGHT_BUTTON()),
                                         $firefox->pause(4),
                                         $firefox->mouse_up(RIGHT_BUTTON()),
                       );

       See the release method for an alternative for manually specifying all the mouse_up and
       key_up methods

   profile_directory
       returns the profile directory used by the current instance of firefox.  This is mainly
       intended for debugging firefox.  Firefox is not designed to cope with these files being
       altered while firefox is running.

   property
       accepts an element as the first parameter and a scalar attribute name as the second
       parameter.  It returns the current value of the property with the supplied name.  This
       method will return the current content, the attribute method will return the initial
       content.

           use Firefox::Marionette();

           my $firefox = Firefox::Marionette->new()->go('https://metacpan.org/');
           my $element = $firefox->find_id('search_input');
           $element->property('value') eq '' or die "Initial property is the empty string";
           $element->type('Test::More');
           $element->property('value') eq 'Test::More' or die "This property should have changed!";

           # OR getting the innerHTML property

           my $title = $firefox->find_tag('title')->property('innerHTML'); # same as $firefox->title();

   pwd_mgr_lock
       Accepts a new primary password <https://support.mozilla.org/en-US/kb/use-primary-password-
       protect-stored-logins> and locks the Password Manager <https://support.mozilla.org/en-
       US/kb/password-manager-remember-delete-edit-logins> with it.

           use Firefox::Marionette();
           use IO::Prompt();

           my $firefox = Firefox::Marionette->new();
           my $password = IO::Prompt::prompt(-echo => q[*], "Please enter the password for the Firefox Password Manager:");
           $firefox->pwd_mgr_lock($password);
           $firefox->pwd_mgr_logout();
           # now no-one can access the Password Manager Database without the value in $password

       This method returns itself to aid in chaining methods.

   pwd_mgr_login
       Accepts the primary password <https://support.mozilla.org/en-US/kb/use-primary-password-
       protect-stored-logins> and allows the user to access the Password Manager
       <https://support.mozilla.org/en-US/kb/password-manager-remember-delete-edit-logins>.

           use Firefox::Marionette();
           use IO::Prompt();

           my $firefox = Firefox::Marionette->new( profile_name => 'default' );
           my $password = IO::Prompt::prompt(-echo => q[*], "Please enter the password for the Firefox Password Manager:");
           $firefox->pwd_mgr_login($password);
           ...
           # access the Password Database.
           ...
           $firefox->pwd_mgr_logout();
           ...
           # no longer able to access the Password Database.

       This method returns itself to aid in chaining methods.

   pwd_mgr_logout
       Logs the user out of being able to access the Password Manager
       <https://support.mozilla.org/en-US/kb/password-manager-remember-delete-edit-logins>.

           use Firefox::Marionette();
           use IO::Prompt();

           my $firefox = Firefox::Marionette->new( profile_name => 'default' );
           my $password = IO::Prompt::prompt(-echo => q[*], "Please enter the password for the Firefox Password Manager:");
           $firefox->pwd_mgr_login($password);
           ...
           # access the Password Database.
           ...
           $firefox->pwd_mgr_logout();
           ...
           # no longer able to access the Password Database.

       This method returns itself to aid in chaining methods.

   pwd_mgr_needs_login
       returns true or false if the Password Manager <https://support.mozilla.org/en-
       US/kb/password-manager-remember-delete-edit-logins> has been locked and needs a primary
       password <https://support.mozilla.org/en-US/kb/use-primary-password-protect-stored-logins>
       to access it.

           use Firefox::Marionette();
           use IO::Prompt();

           my $firefox = Firefox::Marionette->new( profile_name => 'default' );
           if ($firefox->pwd_mgr_needs_login()) {
             my $password = IO::Prompt::prompt(-echo => q[*], "Please enter the password for the Firefox Password Manager:");
             $firefox->pwd_mgr_login($password);
           }

   quit
       Marionette will stop accepting new connections before ending the current session, and
       finally attempting to quit the application.  This method returns the $? (CHILD_ERROR)
       value for the Firefox process

   rect
       accepts a element as the first parameter and returns the current position and size of the
       element

   refresh
       refreshes the current page.  The browser will wait for the page to completely refresh or
       the session's page_load duration to elapse before returning, which, by default is 5
       minutes.  This method returns itself to aid in chaining methods.

   release
       completes any outstanding actions issued by the perform method.

           use Firefox::Marionette();
           use Firefox::Marionette::Keys qw(:all);
           use Firefox::Marionette::Buttons qw(:all);

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

           $firefox->chrome()->perform(
                                        $firefox->key_down(CONTROL()),
                                        $firefox->key_down('l'),
                                      )->release()->content();

           $firefox->go('https://metacpan.org');
           my $help_button = $firefox->find_class('btn search-btn help-btn');
           $firefox->perform(
                                         $firefox->mouse_move($help_button),
                                         $firefox->mouse_down(RIGHT_BUTTON()),
                                         $firefox->pause(4),
                       )->release();

   restart
       restarts the browser.  After the restart, capabilities should be restored.  The same
       profile settings should be applied, but the current state of the browser (such as the uri
       will be reset (like after a normal browser restart).  This method is primarily intended
       for use by the update method.  Not sure if this is useful by itself.

           use Firefox::Marionette();

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

           $firefox->restart(); # but why?

       This method returns itself to aid in chaining methods.

   root_directory
       this is the root directory for the current instance of firefox.  The directory may exist
       on a remote server.  For debugging purposes only.

   screen_orientation
       returns the current browser orientation.  This will be one of the valid primary
       orientation values 'portrait-primary', 'landscape-primary', 'portrait-secondary', or
       'landscape-secondary'.  This method is only currently available on Android (Fennec).

   script
       accepts a scalar containing a javascript function body that is executed in the browser,
       and an optional hash as a second parameter.  Allowed keys are below;

       •   args - The reference to a list is the arguments passed to the function body.

       •   filename - Filename of the client's program where this script is evaluated.

       •   line - Line in the client's program where this script is evaluated.

       •   new - Forces the script to be evaluated in a fresh sandbox.  Note that if it is
           undefined, the script will normally be evaluted in a fresh sandbox.

       •   sandbox - Name of the sandbox to evaluate the script in.  The sandbox is cached for
           later re-use on the same window <https://developer.mozilla.org/en-
           US/docs/Web/API/Window> object if "new" is false.  If he parameter is undefined, the
           script is evaluated in a mutable sandbox.  If the parameter is "system", it will be
           evaluted in a sandbox with elevated system privileges, equivalent to chrome space.

       •   timeout - A timeout to override the default script timeout, which, by default is 30
           seconds.

       Returns the result of the javascript function.  When a parameter is an element (such as
       being returned from a find type operation), the script method will automatically translate
       that into a javascript object.  Likewise, when the result being returned in a script
       method is an element <https://dom.spec.whatwg.org/#concept-element> it will be
       automatically translated into a perl object.

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

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

           if (my $element = $firefox->script('return document.getElementsByName("lucky")[0];')) {
               say "Lucky find is a " . $element->tag_name() . " element";
           }

           my $search_input = $firefox->find_id('metacpan_search-input');

           $firefox->script('arguments[0].style.backgroundColor = "red"', args => [ $search_input ]); # turn the search input box red

       The executing javascript is subject to the script timeout, which, by default is 30
       seconds.

   selfie
       returns a File::Temp object containing a lossless PNG image screenshot.  If an element is
       passed as a parameter, the screenshot will be restricted to the element.

       If an element is not passed as a parameter and the current context is 'chrome', a
       screenshot of the current viewport will be returned.

       If an element is not passed as a parameter and the current context is 'content', a
       screenshot of the current frame will be returned.

       The parameters after the element parameter are taken to be a optional hash with the
       following allowed keys;

       •   hash - return a SHA256 hex encoded digest of the PNG image rather than the image
           itself

       •   full - take a screenshot of the whole document unless the first element parameter has
           been supplied.

       •   raw - rather than a file handle containing the screenshot, the binary PNG image will
           be returned.

       •   scroll - scroll to the element supplied

       •   highlights - a reference to a list containing elements to draw a highlight around.
           Not available in Firefox 70 <https://developer.mozilla.org/en-
           US/docs/Mozilla/Firefox/Releases/70#WebDriver_conformance_Marionette> onwards.

   send_alert_text
       sends keys to the input field of a currently displayed modal message box

   shadow_root
       accepts an element as a parameter and returns it's ShadowRoot
       <https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot> as a shadow root object or
       throws an exception.

           use Firefox::Marionette();
           use Cwd();

           my $firefox = Firefox::Marionette->new()->go('file://' . Cwd::cwd() . '/t/data/elements.html');

           $firefox->find_class('add')->click();
           my $custom_square = $firefox->find_tag('custom-square');
           my $shadow_root = $firefox->shadow_root($custom_square);

           foreach my $element (@{$firefox->script('return arguments[0].children', args => [ $shadow_root ])}) {
               warn $element->tag_name();
           }

   shadowy
       accepts an element as a parameter and returns true if the element has a ShadowRoot
       <https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot> or false otherwise.

           use Firefox::Marionette();
           use Cwd();

           my $firefox = Firefox::Marionette->new()->go('file://' . Cwd::cwd() . '/t/data/elements.html');
           $firefox->find_class('add')->click();
           my $custom_square = $firefox->find_tag('custom-square');
           if ($firefox->shadowy($custom_square)) {
               my $shadow_root = $firefox->find_tag('custom-square')->shadow_root();
               warn $firefox->script('return arguments[0].innerHTML', args => [ $shadow_root ]);
               ...
           }

       This function will probably be used to see if the shadow_root method can be called on this
       element without raising an exception.

   sleep_time_in_ms
       accepts a new time to sleep in await or bye methods and returns the previous time.  The
       default time is "1" millisecond.

           use Firefox::Marionette();

           my $firefox = Firefox::Marionette->new(sleep_time_in_ms => 5); # setting default time to 5 milliseconds

           my $old_time_in_ms = $firefox->sleep_time_in_ms(8); # setting default time to 8 milliseconds, returning 5 (milliseconds)

   ssh_local_directory
       returns the path to the local directory for the ssh connection (if any). For debugging
       purposes only.

   strip
       returns the page source of the content document after an attempt has been made to remove
       typical firefox html wrappers of non html content types such as text/plain and
       application/json.  See the json method for an alternative when dealing with response
       content types such as application/json and html for an alterative when dealing with html
       content types.  This is a convenience method that wraps the html method.

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

           say JSON::decode_json(Firefox::Marionette->new()->go("https://fastapi.metacpan.org/v1/download_url/Firefox::Marionette")->strip())->{version};

       Note that this method will assume the bytes it receives from the html method are UTF-8
       encoded and will translate accordingly, throwing an exception in the process if the bytes
       are not UTF-8 encoded.

   switch_to_frame
       accepts a frame as a parameter and switches to it within the current window.

   switch_to_parent_frame
       set the current browsing context for future commands to the parent of the current browsing
       context

   switch_to_window
       accepts a window handle (either the result of window_handles or a window name as a
       parameter and switches focus to this window.

           use Firefox::Marionette();

           my $firefox = Firefox::Marionette->new();
           $firefox->version
           my $original_window_uuid = $firefox->window_handle();
           $firefox->new_window( type => 'tab' );
           $firefox->new_window( type => 'window' );
           $firefox->switch_to_window($original_window_uuid);
           $firefox->go('https://metacpan.org');

   tag_name
       accepts a Firefox::Marionette::Element object as the first parameter and returns the
       relevant tag name.  For example 'a <https://developer.mozilla.org/en-
       US/docs/Web/HTML/Element/a>' or 'input <https://developer.mozilla.org/en-
       US/docs/Web/HTML/Element/input>'.

   text
       accepts a element as the first parameter and returns the text that is contained by that
       element (if any)

   timeouts
       returns the current timeouts for page loading, searching, and scripts.

   title
       returns the current title <https://developer.mozilla.org/en-
       US/docs/Web/HTML/Element/title> of the window.

   type
       accepts an element as the first parameter and a string as the second parameter.  It sends
       the string to the specified element in the current page, such as filling out a text box.
       This method returns itself to aid in chaining methods.

   update
       queries the Update Services and applies any available updates.  Restarts the browser if
       necessary to complete the update.  This function is experimental and currently has not
       been successfully tested on Win32 or MacOS.

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

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

           my $update = $firefox->update();

           while($update->successful()) {
               $update = $firefox->update();
           }

           say "Updated to " . $update->display_version() . " - Build ID " . $update->build_id();

           $firefox->quit();

       returns a status object that contains useful information about any updates that occurred.

   uninstall
       accepts the GUID for the addon to uninstall.  The GUID is returned when from the install
       method.  This method returns itself to aid in chaining methods.

           use Firefox::Marionette();

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

           my $extension_id = $firefox->install('/full/path/to/gnu_terry_pratchett-0.4-an+fx.xpi');

           # do something

           $firefox->uninstall($extension_id); # not recommended to uninstall this extension IRL.

   uri
       returns the current URI of current top level browsing context for Desktop.  It is
       equivalent to the javascript "document.location.href"

   win32_organisation
       accepts a parameter of a Win32 product name and returns the matching organisation.  Only
       of interest when sub-classing.

   win32_product_names
       returns a hash of known Windows product names (such as 'Mozilla Firefox') with priority
       orders.  The lower the priority will determine the order that this module will check for
       the existance of this product.  Only of interest when sub-classing.

   window_handle
       returns the current window's handle. On desktop this typically corresponds to the
       currently selected tab.  returns an opaque server-assigned identifier to this window that
       uniquely identifies it within this Marionette instance.  This can be used to switch to
       this window at a later point.

           use Firefox::Marionette();
           use 5.010;

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

   window_handles
       returns a list of top-level browsing contexts. On desktop this typically corresponds to
       the set of open tabs for browser windows, or the window itself for non-browser chrome
       windows.  Each window handle is assigned by the server and is guaranteed unique, however
       the return array does not have a specified ordering.

           use Firefox::Marionette();
           use 5.010;

           my $firefox = Firefox::Marionette->new();
           my $original_window_uuid = $firefox->window_handle();
           $firefox->new_window( type => 'tab' );
           $firefox->new_window( type => 'window' );
           say "There are " . $firefox->window_handles() . " tabs open in total";
           say "Across " . $firefox->chrome()->window_handles()->content() . " chrome windows";

   window_rect
       accepts an optional position and size as a parameter, sets the current browser window to
       that position and size and returns the previous position, size and state of the browser
       window.  If no parameter is supplied, it returns the current  position, size and state of
       the browser window.

   window_type
       returns the current window's type.  This should be 'navigator:browser'.

   xvfb_pid
       returns the pid of the xvfb process if it exists.

   xvfb_display
       returns the value for the DISPLAY environment variable if one has been generated for the
       xvfb environment.

   xvfb_xauthority
       returns the value for the XAUTHORITY environment variable if one has been generated for
       the xvfb environment

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

REMOTE AUTOMATION OF FIREFOX VIA SSH

           use Firefox::Marionette();

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

           # OR specify a different user to login as ...

           my $firefox = Firefox::Marionette->new( host => 'remote.example.org', user => 'R2D2', debug => 1 );
           $firefox->go('https://metacpan.org/');

           # OR specify a different port to connect to

           my $firefox = Firefox::Marionette->new( host => 'remote.example.org', port => 2222, debug => 1 );
           $firefox->go('https://metacpan.org/');

       This module has support for creating and automating an instance of Firefox on a remote
       node.  It has been tested against a number of operating systems, including recent version
       of Windows 10 or Windows Server 2019 <https://docs.microsoft.com/en-us/windows-
       server/administration/openssh/openssh_install_firstuse>, OS X, and Linux and BSD
       distributions.  It expects to be able to login to the remote node via public key
       authentication.  It can be further secured via the command
       <https://man.openbsd.org/sshd#command=_command_> option in the OpenSSH
       <https://www.openssh.com/> authorized_keys
       <https://man.openbsd.org/sshd#AUTHORIZED_KEYS_FILE_FORMAT> file such as;

           no-agent-forwarding,no-pty,no-X11-forwarding,permitopen="127.0.0.1:*",command="/usr/local/bin/ssh-auth-cmd-marionette" ssh-rsa AAAA ... == user@server

       As an example, the ssh-auth-cmd-marionette command is provided as part of this
       distribution.

       When using ssh, Firefox::Marionette will attempt to pass the TMPDIR
       <https://en.wikipedia.org/wiki/TMPDIR> environment variable across the ssh connection to
       make cleanups easier.  In order to allow this, the AcceptEnv
       <https://man.openbsd.org/sshd_config#AcceptEnv> setting in the remote sshd configuration
       <https://man.openbsd.org/sshd_config> should be set to allow TMPDIR, which will look like;

           AcceptEnv TMPDIR

       This module uses ControlMaster <https://man.openbsd.org/ssh_config#ControlMaster>
       functionality when using ssh <https://man.openbsd.org/ssh>, for a useful speedup of
       executing remote commands.  Unfortunately, when using ssh to move from a cygwin
       <https://gcc.gnu.org/wiki/SSH_connection_caching>, Windows 10 or Windows Server 2019
       <https://docs.microsoft.com/en-us/windows-
       server/administration/openssh/openssh_install_firstuse> node to a remote environment, we
       cannot use ControlMaster <https://man.openbsd.org/ssh_config#ControlMaster>, because at
       this time, Windows does not support ControlMaster <https://github.com/Microsoft/vscode-
       remote-release/issues/96> and therefore this type of automation is still possible, but
       slower than other client platforms.

DIAGNOSTICS

       "Failed to correctly setup the Firefox process"
           The module was unable to retrieve a session id and capabilities from Firefox when it
           requests a new_session as part of the initial setup of the connection to Firefox.

       "Failed to correctly determined the Firefox process id through the initial connection
       capabilities"
           The module was found that firefox is reporting through it's Capabilities object a
           different process id than this module was using.  This is probably a bug in this
           module's logic.  Please report as described in the BUGS AND LIMITATIONS section below.

       "'%s --version' did not produce output that could be parsed.  Assuming modern Marionette
       is available:%s"
           The Firefox binary did not produce a version number that could be recognised as a
           Firefox version number.

       "Failed to create process from '%s':%s"
           The module was to start Firefox process in a Win32 environment.  Something is
           seriously wrong with your environment.

       "Failed to redirect %s to %s:%s"
           The module was unable to redirect a file handle's output.  Something is seriously
           wrong with your environment.

       "Failed to exec %s:%s"
           The module was unable to run the Firefox binary.  Check the path is correct and the
           current user has execute permissions.

       "Failed to fork:%s"
           The module was unable to fork itself, prior to executing a command.  Check the current
           "ulimit" for max number of user processes.

       "Failed to open directory '%s':%s"
           The module was unable to open a directory.  Something is seriously wrong with your
           environment.

       "Failed to close directory '%s':%s"
           The module was unable to close a directory.  Something is seriously wrong with your
           environment.

       "Failed to open '%s' for writing:%s"
           The module was unable to create a file in your temporary directory.  Maybe your disk
           is full?

       "Failed to open temporary file for writing:%s"
           The module was unable to create a file in your temporary directory.  Maybe your disk
           is full?

       "Failed to close '%s':%s"
           The module was unable to close a file in your temporary directory.  Maybe your disk is
           full?

       "Failed to close temporary file:%s"
           The module was unable to close a file in your temporary directory.  Maybe your disk is
           full?

       "Failed to create temporary directory:%s"
           The module was unable to create a directory in your temporary directory.  Maybe your
           disk is full?

       "Failed to clear the close-on-exec flag on a temporary file:%s"
           The module was unable to call fcntl using F_SETFD for a file in your temporary
           directory.  Something is seriously wrong with your environment.

       "Failed to seek to start of temporary file:%s"
           The module was unable to seek to the start of a file in your temporary directory.
           Something is seriously wrong with your environment.

       "Failed to create a socket:%s"
           The module was unable to even create a socket.  Something is seriously wrong with your
           environment.

       "Failed to connect to %s on port %d:%s"
           The module was unable to connect to the Marionette port.  This is probably a bug in
           this module's logic.  Please report as described in the BUGS AND LIMITATIONS section
           below.

       "Firefox killed by a %s signal (%d)"
           Firefox crashed after being hit with a signal.

       "Firefox exited with a %d"
           Firefox has exited with an error code

       "Failed to bind socket:%s"
           The module was unable to bind a socket to any port.  Something is seriously wrong with
           your environment.

       "Failed to close random socket:%s"
           The module was unable to close a socket without any reads or writes being performed on
           it.  Something is seriously wrong with your environment.

       "moz:headless has not been determined correctly"
           The module was unable to correctly determine whether Firefox is running in "headless"
           or not.  This is probably a bug in this module's logic.  Please report as described in
           the BUGS AND LIMITATIONS section below.

       "%s method requires a Firefox::Marionette::Element parameter"
           This function was called incorrectly by your code.  Please supply a
           Firefox::Marionette::Element parameter when calling this function.

       "Failed to write to temporary file:%s"
           The module was unable to write to a file in your temporary directory.  Maybe your disk
           is full?

       "Failed to close socket to firefox:%s"
           The module was unable to even close a socket.  Something is seriously wrong with your
           environment.

       "Failed to send request to firefox:%s"
           The module was unable to perform a syswrite on the socket connected to firefox.  Maybe
           firefox crashed?

       "Failed to read size of response from socket to firefox:%s"
           The module was unable to read from the socket connected to firefox.  Maybe firefox
           crashed?

       "Failed to read response from socket to firefox:%s"
           The module was unable to read from the socket connected to firefox.  Maybe firefox
           crashed?

CONFIGURATION AND ENVIRONMENT

       Firefox::Marionette requires no configuration files or environment variables.  It will
       however use the DISPLAY and XAUTHORITY environment variables to try to connect to an X
       Server.  It will also use the HTTP_PROXY, HTTPS_PROXY, FTP_PROXY and ALL_PROXY environment
       variables as defaults if the session capabilities do not specify proxy information.

DEPENDENCIES

       Firefox::Marionette requires the following non-core Perl modules

       •   JSON

       •   URI

       •   XML::Parser

INCOMPATIBILITIES

       None reported.  Always interested in any products with marionette support that this module
       could be patched to work with.

BUGS AND LIMITATIONS

   DOWNLOADING USING GO METHOD
       When using the go method to go directly to a URL containing a downloadable file, Firefox
       can hang.  You can work around this by setting the page_load_strategy to "none" like
       below;

           #! /usr/bin/perl

           use strict;
           use warnings;
           use Firefox::Marionette();

           my $firefox = Firefox::Marionette->new( capabilities => Firefox::Marionette::Capabilities->new( page_load_strategy => 'none' ) );
           $firefox->go("https://github.com/david-dick/firefox-marionette/archive/refs/heads/master.zip");
           while(!$firefox->downloads()) { sleep 1 }
           while($firefox->downloading()) { sleep 1 }
           foreach my $path ($firefox->downloads()) {
               warn "$path has been downloaded";
           }
           $firefox->quit();

   MISSING METHODS
       Currently the following Marionette methods have not been implemented;

       •   WebDriver:SetScreenOrientation

       To report a bug, or view the current list of bugs, please visit
       <https://github.com/david-dick/firefox-marionette/issues>

SEE ALSO

       •   MozRepl

       •   Selenium::Firefox

       •   Firefox::Application

       •   Mozilla::Mechanize

       •   Gtk2::MozEmbed

AUTHOR

       David Dick  "<ddick@cpan.org>"

ACKNOWLEDGEMENTS

       Thanks to the entire Mozilla organisation for a great browser and to the team behind
       Marionette for providing an interface for automation.

       Thanks to Jan Odvarko <http://www.softwareishard.com/blog/about/> for creating the HAR
       Export Trigger <https://github.com/firefox-devtools/har-export-trigger> extension for
       Firefox.

       Thanks to Mike Kaply <https://mike.kaply.com/about/> for his post
       <https://mike.kaply.com/2015/02/10/installing-certificates-into-firefox/> describing
       importing certificates into Firefox.

       Thanks also to the authors of the documentation in the following sources;

       •   Marionette Protocol <https://firefox-source-
           docs.mozilla.org/testing/marionette/marionette/index.html>

       •   Marionette Documentation <https://firefox-source-
           docs.mozilla.org/testing/marionette/marionette/index.html>

       •   Marionette driver.js <https://hg.mozilla.org/mozilla-
           central/file/tip/remote/marionette/driver.js>

       •   about:config <http://kb.mozillazine.org/About:config_entries>

       •   nsIPrefService interface <https://developer.mozilla.org/en-
           US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIPrefService>

LICENSE AND COPYRIGHT

       Copyright (c) 2021, David Dick "<ddick@cpan.org>". All rights reserved.

       This module is free software; you can redistribute it and/or modify it under the same
       terms as Perl itself. See "perlartistic" in perlartistic.

       The Firefox::Marionette::Extension::HarExportTrigger module includes the HAR Export
       Trigger <https://github.com/firefox-devtools/har-export-trigger> extension which is
       licensed under the Mozilla Public License 2.0 <https://www.mozilla.org/en-US/MPL/2.0/>.

DISCLAIMER OF WARRANTY

       BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE,
       TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE
       COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF
       ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
       WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO
       THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE
       DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.

       IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT
       HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY
       THE ABOVE LICENCE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,
       INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
       SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR
       LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY
       OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
       SUCH DAMAGES.