package Selenium::Firefox::Binary; use strict; use warnings; # ABSTRACT: Subroutines for locating and properly initializing the Firefox Binary use File::Which qw/which/; use Selenium::Firefox::Profile; require Exporter; our @ISA = qw/Exporter/; our @EXPORT_OK = qw/firefox_path setup_firefox_binary_env/; sub _firefox_windows_path { # TODO: make this slightly less dumb my @program_files = ( $ENV{PROGRAMFILES} // 'C:\Program Files', $ENV{'PROGRAMFILES(X86)'} // 'C:\Program Files (x86)', ); foreach (@program_files) { my $binary_path = $_ . '\Mozilla Firefox\firefox.exe'; return $binary_path if -x $binary_path; } # Fall back to a completely naive strategy warn q/We couldn't find a viable firefox.EXE; you may want to specify it via the binary attribute./; return which('firefox'); } sub _firefox_darwin_path { my $default_firefox = '/Applications/Firefox.app/Contents/MacOS/firefox-bin'; if ( -e $default_firefox && -x $default_firefox ) { return $default_firefox; } else { return which('firefox-bin'); } } sub _firefox_unix_path { # TODO: maybe which('firefox3'), which('firefox2') ? return which('firefox') || '/usr/bin/firefox'; } =head1 SUBROUTINES =head2 firefox_path Return the path to the firefox binary on your system. =cut sub firefox_path { my $path; if ( $^O eq 'MSWin32' ) { $path = _firefox_windows_path(); } elsif ( $^O eq 'darwin' ) { $path = _firefox_darwin_path(); } else { $path = _firefox_unix_path; } if ( not -x $path ) { die $path . ' is not an executable file.'; } return $path; } =head2 setup_firefox_binary_env Sets various environment variables to make firefox work correctly with webDriver. =cut # We want the profile to persist to the end of the session, not just # the end of this function. my $profile; sub setup_firefox_binary_env { my ( $port, $marionette_port, $caller_profile ) = @_; $profile = $caller_profile || Selenium::Firefox::Profile->new; $profile->add_webdriver( $port, $marionette_port ); $profile->add_marionette($marionette_port); # For non-geckodriver/marionette startup, we instruct Firefox to # use the profile by specifying the appropriate environment # variables for it to hook onto. if ( !$marionette_port ) { $ENV{'XRE_PROFILE_PATH'} = $profile->_layout_on_disk; $ENV{'MOZ_NO_REMOTE'} = '1'; # able to launch multiple instances $ENV{'MOZ_CRASHREPORTER_DISABLE'} = '1'; # disable breakpad $ENV{'NO_EM_RESTART'} = '1'; # prevent the binary from detaching from the console.log } else { # In case the user created an old Firefox, which would've set # those ENV variables, and then wanted to create a new Firefox # afterwards, the env variables would still be around, and the # new Firefox would respect the XRE_PROFILE_PATH and try to # load it in the new geckodriver Firefox, which would cause an # extension compatibility check my @env_vars = qw/ XRE_PROFILE_PATH MOZ_NO_REMOTE MOZ_CRASHREPORTER_DISABLE NO_EM_RESTART /; foreach (@env_vars) { delete $ENV{$_}; } } return $profile; } 1;