BinaryModeBuilder.pm 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. package Selenium::BinaryModeBuilder;
  2. # ABSTRACT: Teach a WebDriver how to start its own binary aka no JRE!
  3. use File::Which qw/which/;
  4. use IO::Socket::INET;
  5. use Selenium::Waiter qw/wait_until/;
  6. use Selenium::Firefox::Binary qw/firefox_path setup_firefox_binary_env/;
  7. use Selenium::Firefox::Profile;
  8. use Try::Tiny;
  9. use Moo::Role;
  10. has 'binary_mode' => (
  11. is => 'ro',
  12. init_arg => undef,
  13. lazy => 1,
  14. builder => 1
  15. );
  16. sub _build_binary_mode {
  17. my ($self) = @_;
  18. if (! $self->has_remote_server_addr && ! $self->has_port) {
  19. try {
  20. my $port = start_binary_on_port($self->binary_name, $self->binary_port);
  21. $self->port($port);
  22. return 1;
  23. }
  24. catch {
  25. warn $_;
  26. return 0;
  27. }
  28. }
  29. else {
  30. return 0;
  31. }
  32. }
  33. sub probe_port {
  34. my ($port) = @_;
  35. return IO::Socket::INET->new(
  36. PeerAddr => '127.0.0.1',
  37. PeerPort => $port,
  38. Timeout => 3
  39. );
  40. }
  41. sub start_binary_on_port {
  42. my ($process, $port) = @_;
  43. my $executable = _find_executable($process);
  44. $port = _find_open_port_above($port);
  45. if ($process eq 'firefox') {
  46. setup_firefox_binary_env($port);
  47. }
  48. my $command = _construct_command($executable, $port);
  49. system($command);
  50. my $success = wait_until { probe_port($port) } timeout => 10;
  51. if ($success) {
  52. return $port;
  53. }
  54. else {
  55. die 'Unable to connect to the ' . $executable . ' binary on port ' . $port;
  56. }
  57. }
  58. sub _find_executable {
  59. my ($binary) = @_;
  60. if ($binary eq 'firefox') {
  61. return firefox_path();
  62. }
  63. else {
  64. my $executable = which($binary);
  65. if (not defined $executable) {
  66. die qq(Unable to find the $binary binary in your \$PATH. We'll try falling back to standard Remote Driver);
  67. }
  68. else {
  69. return $executable;
  70. }
  71. }
  72. }
  73. sub _construct_command {
  74. my ($executable, $port) = @_;
  75. my %args;
  76. if ($executable =~ /chromedriver$/) {
  77. %args = (
  78. port => $port,
  79. 'url-base' => 'wd/hub'
  80. );
  81. }
  82. elsif ($executable =~ /phantomjs$/) {
  83. %args = (
  84. webdriver => '127.0.0.1:' . $port
  85. );
  86. }
  87. elsif ($executable =~ /firefox/i) {
  88. $executable .= ' -no-remote ';
  89. }
  90. my @args = map { '--' . $_ . '=' . $args{$_} } keys %args;
  91. return join(' ', ($executable, @args, '> /dev/null 2>&1 &') );
  92. }
  93. sub _find_open_port_above {
  94. my ($port) = @_;
  95. my $free_port = wait_until {
  96. if ( probe_port($port) ) {
  97. $port++;
  98. return 0;
  99. }
  100. else {
  101. return $port;
  102. }
  103. };
  104. return $free_port;
  105. }
  106. 1;