Class: Ferrum::Browser::Process
- Inherits:
-
Object
- Object
- Ferrum::Browser::Process
- Extended by:
- Forwardable
- Defined in:
- lib/ferrum/browser/process.rb
Overview
Constant Summary collapse
- KILL_TIMEOUT =
2- WAIT_KILLED =
0.05
Instance Attribute Summary collapse
-
#browser_version ⇒ Object
readonly
Returns the value of attribute browser_version.
-
#command ⇒ Object
readonly
Returns the value of attribute command.
-
#default_user_agent ⇒ Object
readonly
Returns the value of attribute default_user_agent.
-
#host ⇒ Object
readonly
Returns the value of attribute host.
-
#pid ⇒ Object
readonly
Returns the value of attribute pid.
-
#port ⇒ Object
readonly
Returns the value of attribute port.
-
#protocol_version ⇒ Object
readonly
Returns the value of attribute protocol_version.
-
#v8_version ⇒ Object
readonly
Returns the value of attribute v8_version.
-
#webkit_version ⇒ Object
readonly
Returns the value of attribute webkit_version.
-
#ws_url ⇒ Object
readonly
Returns the value of attribute ws_url.
-
#xvfb ⇒ Object
readonly
Returns the value of attribute xvfb.
Class Method Summary collapse
-
.directory_remover(path) ⇒ Proc
Builds a finalizer proc that removes the directory at the given path.
-
.process_killer(pid) ⇒ Proc
Builds a finalizer proc that kills the process with the given pid.
-
.start(*args) ⇒ Process
Builds and starts a new browser process.
Instance Method Summary collapse
-
#initialize(options) ⇒ Process
constructor
A new instance of Process.
-
#inspect ⇒ String
Custom inspection that omits noisy internal command details.
-
#restart ⇒ void
Stops and starts the browser process again.
-
#start ⇒ void
Spawns the browser process and waits for it to become reachable over CDP.
-
#stop ⇒ void
Kills the browser process (and Xvfb, if running) and removes the user data directory.
Constructor Details
#initialize(options) ⇒ Process
Returns a new instance of Process.
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/ferrum/browser/process.rb', line 95 def initialize() @pid = @xvfb = @user_data_dir = nil if .ws_url || .url # `:ws_url` option is higher priority than `:url`, parse versions # and use it as a ws_url, otherwise use what has been parsed. response = parse_json_version(.ws_url || .url) self.ws_url = .ws_url || response&.[]("webSocketDebuggerUrl") return end @logger = .logger @process_timeout = .process_timeout @env = Hash(.env) tmpdir = Dir.mktmpdir("ferrum_user_data_dir_") ObjectSpace.define_finalizer(self, self.class.directory_remover(tmpdir)) @user_data_dir = tmpdir @command = Command.build(, tmpdir) end |
Instance Attribute Details
#browser_version ⇒ Object (readonly)
Returns the value of attribute browser_version.
91 92 93 |
# File 'lib/ferrum/browser/process.rb', line 91 def browser_version @browser_version end |
#command ⇒ Object (readonly)
Returns the value of attribute command.
91 92 93 |
# File 'lib/ferrum/browser/process.rb', line 91 def command @command end |
#default_user_agent ⇒ Object (readonly)
Returns the value of attribute default_user_agent.
91 92 93 |
# File 'lib/ferrum/browser/process.rb', line 91 def default_user_agent @default_user_agent end |
#host ⇒ Object (readonly)
Returns the value of attribute host.
91 92 93 |
# File 'lib/ferrum/browser/process.rb', line 91 def host @host end |
#pid ⇒ Object (readonly)
Returns the value of attribute pid.
91 92 93 |
# File 'lib/ferrum/browser/process.rb', line 91 def pid @pid end |
#port ⇒ Object (readonly)
Returns the value of attribute port.
91 92 93 |
# File 'lib/ferrum/browser/process.rb', line 91 def port @port end |
#protocol_version ⇒ Object (readonly)
Returns the value of attribute protocol_version.
91 92 93 |
# File 'lib/ferrum/browser/process.rb', line 91 def protocol_version @protocol_version end |
#v8_version ⇒ Object (readonly)
Returns the value of attribute v8_version.
91 92 93 |
# File 'lib/ferrum/browser/process.rb', line 91 def v8_version @v8_version end |
#webkit_version ⇒ Object (readonly)
Returns the value of attribute webkit_version.
91 92 93 |
# File 'lib/ferrum/browser/process.rb', line 91 def webkit_version @webkit_version end |
#ws_url ⇒ Object
Returns the value of attribute ws_url.
91 92 93 |
# File 'lib/ferrum/browser/process.rb', line 91 def ws_url @ws_url end |
#xvfb ⇒ Object (readonly)
Returns the value of attribute xvfb.
91 92 93 |
# File 'lib/ferrum/browser/process.rb', line 91 def xvfb @xvfb end |
Class Method Details
.directory_remover(path) ⇒ Proc
Builds a finalizer proc that removes the directory at the given path.
81 82 83 84 85 86 87 88 89 |
# File 'lib/ferrum/browser/process.rb', line 81 def self.directory_remover(path) proc { begin FileUtils.remove_entry(path) rescue StandardError Errno::ENOENT end } end |
.process_killer(pid) ⇒ Proc
Builds a finalizer proc that kills the process with the given pid.
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/ferrum/browser/process.rb', line 51 def self.process_killer(pid) proc do if Utils::Platform.windows? # Process.kill is unreliable on Windows ::Process.kill("KILL", pid) unless system("taskkill /f /t /pid #{pid} >NUL 2>NUL") else ::Process.kill("USR1", pid) start = Utils::ElapsedTime.monotonic_time while ::Process.wait(pid, ::Process::WNOHANG).nil? sleep(WAIT_KILLED) next unless Utils::ElapsedTime.timeout?(start, KILL_TIMEOUT) ::Process.kill("KILL", pid) ::Process.wait(pid) break end end rescue Errno::ESRCH, Errno::ECHILD # nop end end |
.start(*args) ⇒ Process
Builds and starts a new browser process.
39 40 41 |
# File 'lib/ferrum/browser/process.rb', line 39 def self.start(*args) new(*args).tap(&:start) end |
Instance Method Details
#inspect ⇒ String
Custom inspection that omits noisy internal command details.
179 180 181 182 183 184 185 186 187 188 |
# File 'lib/ferrum/browser/process.rb', line 179 def inspect "#<#{self.class} " \ "@user_data_dir=#{@user_data_dir.inspect} " \ "@command=#<#{@command.class}:#{@command.object_id}> " \ "@default_user_agent=#{@default_user_agent.inspect} " \ "@ws_url=#{@ws_url.inspect} " \ "@v8_version=#{@v8_version.inspect} " \ "@browser_version=#{@browser_version.inspect} " \ "@webkit_version=#{@webkit_version.inspect}>" end |
#restart ⇒ void
This method returns an undefined value.
Stops and starts the browser process again.
169 170 171 172 |
# File 'lib/ferrum/browser/process.rb', line 169 def restart stop start end |
#start ⇒ void
This method returns an undefined value.
Spawns the browser process and waits for it to become reachable over CDP.
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/ferrum/browser/process.rb', line 121 def start # Don't do anything as browser is already running as external process. return if ws_url begin read_io, write_io = IO.pipe = { in: File::NULL } [:pgroup] = true unless Utils::Platform.windows? [:out] = [:err] = write_io if @command.xvfb? @xvfb = Xvfb.start(@command.) ObjectSpace.define_finalizer(self, self.class.process_killer(@xvfb.pid)) end env = Hash(@xvfb&.to_env).merge(@env) @pid = ::Process.spawn(env, *@command.to_a, ) ObjectSpace.define_finalizer(self, self.class.process_killer(@pid)) parse_ws_url(read_io, @process_timeout) parse_json_version(ws_url) ensure close_io(read_io, write_io) end end |
#stop ⇒ void
This method returns an undefined value.
Kills the browser process (and Xvfb, if running) and removes the user data directory.
153 154 155 156 157 158 159 160 161 162 |
# File 'lib/ferrum/browser/process.rb', line 153 def stop if @pid kill(@pid) kill(@xvfb.pid) if @xvfb&.pid @pid = nil end remove_user_data_dir if @user_data_dir ObjectSpace.undefine_finalizer(self) end |