Class: Capybara::Cuprite::Browser::Process

Inherits:
Object
  • Object
show all
Defined in:
lib/capybara/cuprite/browser/process.rb

Constant Summary collapse

KILL_TIMEOUT =
2
BROWSER_PATH =
ENV.fetch("BROWSER_PATH", "chrome")
BROWSER_HOST =
"127.0.0.1"
BROWSER_PORT =
"0"
DEFAULT_OPTIONS =
{
  "headless" => nil,
  "disable-gpu" => nil,
  "hide-scrollbars" => nil,
  "mute-audio" => nil,
  # Note: --no-sandbox is not needed if you properly setup a user in the container.
  # https://github.com/ebidel/lighthouse-ci/blob/master/builder/Dockerfile#L35-L40
  # "no-sandbox" => nil,
  "enable-automation" => nil,
  "disable-web-security" => nil,
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ Process

Returns a new instance of Process.



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/capybara/cuprite/browser/process.rb', line 55

def initialize(options)
  @options = options.fetch(:browser, {})
  exe = options[:path] || BROWSER_PATH
  @path = Cliver.detect(exe)

  unless @path
    message = "Could not find an executable `#{exe}`. Try to make it " \
              "available on the PATH or set environment varible for " \
              "example BROWSER_PATH=\"/Applications/Chromium.app/Contents/MacOS/Chromium\""
    raise Cliver::Dependency::NotFound.new(message)
  end

  window_size = options.fetch(:window_size, [1024, 768])
  @options = @options.merge("window-size" => window_size.join(","))

  port = options.fetch(:port, BROWSER_PORT)
  @options = @options.merge("remote-debugging-port" => port)

  host = options.fetch(:host, BROWSER_HOST)
  @options = @options.merge("remote-debugging-address" => host)

  @options = DEFAULT_OPTIONS.merge(@options)
end

Instance Attribute Details

#hostObject (readonly)

Returns the value of attribute host.



28
29
30
# File 'lib/capybara/cuprite/browser/process.rb', line 28

def host
  @host
end

#optionsObject (readonly)

Returns the value of attribute options.



28
29
30
# File 'lib/capybara/cuprite/browser/process.rb', line 28

def options
  @options
end

#pidObject (readonly)

Returns the value of attribute pid.



28
29
30
# File 'lib/capybara/cuprite/browser/process.rb', line 28

def pid
  @pid
end

#portObject (readonly)

Returns the value of attribute port.



28
29
30
# File 'lib/capybara/cuprite/browser/process.rb', line 28

def port
  @port
end

#ws_urlObject (readonly)

Returns the value of attribute ws_url.



28
29
30
# File 'lib/capybara/cuprite/browser/process.rb', line 28

def ws_url
  @ws_url
end

Class Method Details

.process_killer(pid) ⇒ Object



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/capybara/cuprite/browser/process.rb', line 34

def self.process_killer(pid)
  proc do
    begin
      if Capybara::Cuprite.windows?
        ::Process.kill("KILL", pid)
      else
        ::Process.kill("TERM", pid)
        start = Time.now
        while ::Process.wait(pid, ::Process::WNOHANG).nil?
          sleep 0.05
          next unless (Time.now - start) > KILL_TIMEOUT
          ::Process.kill("KILL", pid)
          ::Process.wait(pid)
          break
        end
      end
    rescue Errno::ESRCH, Errno::ECHILD
    end
  end
end

.start(*args) ⇒ Object



30
31
32
# File 'lib/capybara/cuprite/browser/process.rb', line 30

def self.start(*args)
  new(*args).tap(&:start)
end

Instance Method Details

#restartObject



104
105
106
107
# File 'lib/capybara/cuprite/browser/process.rb', line 104

def restart
  stop
  start
end

#startObject



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/capybara/cuprite/browser/process.rb', line 79

def start
  read_io, write_io = IO.pipe
  process_options = { in: File::NULL }
  process_options[:pgroup] = true unless Capybara::Cuprite.windows?
  if Capybara::Cuprite.mri?
    process_options[:out] = process_options[:err] = write_io
  end

  redirect_stdout(write_io) do
    cmd = [@path] + @options.map { |k, v| v.nil? ? "--#{k}" : "--#{k}=#{v}" }
    @pid = ::Process.spawn(*cmd, process_options)
    ObjectSpace.define_finalizer(self, self.class.process_killer(@pid))
  end

  parse_ws_url(read_io)
ensure
  close_io(read_io, write_io)
end

#stopObject



98
99
100
101
102
# File 'lib/capybara/cuprite/browser/process.rb', line 98

def stop
  return unless @pid
  kill
  ObjectSpace.undefine_finalizer(self)
end