1
0

Chrome.pm 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. package Selenium::Chrome;
  2. # ABSTRACT: A convenience package for creating a Chrome instance
  3. use File::Which qw/which/;
  4. use IO::Socket::INET;
  5. use Selenium::Waiter qw/wait_until/;
  6. use Moo;
  7. use namespace::clean;
  8. extends 'Selenium::Remote::Driver';
  9. =head1 SYNOPSIS
  10. my $driver = Selenium::Chrome->new;
  11. =cut
  12. my $default_binary_server = '127.0.0.1';
  13. my $default_binary_port = 9515;
  14. has '+browser_name' => (
  15. is => 'ro',
  16. default => sub { 'chrome' }
  17. );
  18. has '+port' => (
  19. is => 'lazy'
  20. );
  21. has 'binary_mode' => (
  22. is => 'ro',
  23. init_arg => undef,
  24. builder => sub {
  25. my ($self) = @_;
  26. if (! $self->has_remote_server_addr && ! $self->has_port) {
  27. my $executable = _find_executable('chromedriver');
  28. my $port = _find_open_port_above($default_binary_port);
  29. my $command = _construct_command($executable, $port);
  30. system($command);
  31. my $success = wait_until { _query_port($port) } timeout => 10;
  32. if ($success) {
  33. $self->port($port);
  34. }
  35. else {
  36. warn qq(
  37. Unable to start up the chromedriver binary via:
  38. $command
  39. We'll try falling back to standard Remote Driver mode via the webdriver.chrome.driver property...
  40. );
  41. }
  42. return 1;
  43. }
  44. else {
  45. return 0;
  46. }
  47. }
  48. );
  49. sub _find_executable {
  50. my ($binary) = @_;
  51. my $executable = which($binary);
  52. if (not defined $executable) {
  53. warn q(
  54. Unable to find the chromedriver binary in your $PATH. Please download the server from http://chromedriver.storage.googleapis.com/index.html and place it somewhere on your $PATH. More info is available at http://code.google.com/p/selenium/wiki/ChromeDriver.
  55. We'll try falling back to standard Remote Driver mode via the webdriver.chrome.driver property...
  56. );
  57. }
  58. return $executable;
  59. }
  60. sub _construct_command {
  61. my ($executable, $port) = @_;
  62. my %args = (
  63. 'base-url' => 'wd/hub',
  64. 'port' => $port
  65. );
  66. my @args = map { '--' . $_ . '=' . $args{$_} } keys %args;
  67. return join(' ', ($executable, @args, '> /dev/null 2>&1 &') );
  68. }
  69. sub _find_open_port_above {
  70. my ($port) = @_;
  71. my $free_port = wait_until {
  72. if (_probe_port($port)) {
  73. $port++;
  74. return 0;
  75. }
  76. else {
  77. return $port;
  78. }
  79. };
  80. return $free_port;
  81. }
  82. sub _probe_port {
  83. my ($port) = @_;
  84. return IO::Socket::INET->new(
  85. PeerAddr => $default_binary_server,
  86. PeerPort => $port,
  87. Timeout => 3
  88. );
  89. }
  90. sub DEMOLISH {
  91. my ($self) = @_;
  92. my $port = $self->port;
  93. my $ua = LWP::UserAgent->new;
  94. $ua->get($default_binary_server . ':' . $port . '/wd/hub/shutdown');
  95. }
  96. 1;