ferrum 0.12 → 0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +28 -22
- data/lib/ferrum/browser/client.rb +6 -5
- data/lib/ferrum/browser/command.rb +9 -6
- data/lib/ferrum/browser/options/base.rb +1 -4
- data/lib/ferrum/browser/options/chrome.rb +22 -10
- data/lib/ferrum/browser/options/firefox.rb +3 -6
- data/lib/ferrum/browser/options.rb +84 -0
- data/lib/ferrum/browser/process.rb +6 -7
- data/lib/ferrum/browser/version_info.rb +71 -0
- data/lib/ferrum/browser/web_socket.rb +1 -1
- data/lib/ferrum/browser/xvfb.rb +1 -1
- data/lib/ferrum/browser.rb +184 -64
- data/lib/ferrum/context.rb +3 -2
- data/lib/ferrum/contexts.rb +2 -2
- data/lib/ferrum/cookies/cookie.rb +183 -0
- data/lib/ferrum/cookies.rb +122 -49
- data/lib/ferrum/dialog.rb +30 -0
- data/lib/ferrum/frame/dom.rb +177 -0
- data/lib/ferrum/frame/runtime.rb +41 -61
- data/lib/ferrum/frame.rb +91 -3
- data/lib/ferrum/headers.rb +28 -0
- data/lib/ferrum/keyboard.rb +45 -2
- data/lib/ferrum/mouse.rb +84 -0
- data/lib/ferrum/network/exchange.rb +104 -5
- data/lib/ferrum/network/intercepted_request.rb +3 -12
- data/lib/ferrum/network/request.rb +58 -19
- data/lib/ferrum/network/request_params.rb +57 -0
- data/lib/ferrum/network/response.rb +106 -4
- data/lib/ferrum/network.rb +193 -8
- data/lib/ferrum/node.rb +21 -1
- data/lib/ferrum/page/animation.rb +16 -0
- data/lib/ferrum/page/frames.rb +66 -11
- data/lib/ferrum/page/screenshot.rb +97 -0
- data/lib/ferrum/page/tracing.rb +26 -0
- data/lib/ferrum/page.rb +158 -45
- data/lib/ferrum/proxy.rb +91 -2
- data/lib/ferrum/target.rb +6 -4
- data/lib/ferrum/version.rb +1 -1
- metadata +7 -101
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6cbef2f4caac663a8b39afc37b94e46f00c9471cdaea36a1781dcfa99488a546
|
4
|
+
data.tar.gz: 58d8f68e84138b71de15ac33368d4cd4f8992db4ab7f321a3e3f03530968502b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a621c8e99fe1ec5e183ad54681da4a6bf09105fc66477c37b76b59cb1842f679ac679690514de1829fbbe18af4b81e0e01a64b564a48db9c49af151fc5b64e51
|
7
|
+
data.tar.gz: cc3089d1b9a81d43e8dbeb356b0d677d5377bc1d1d4667e0da9f389034e044ef0497ced614b39812cff53dd70930ec1f66e473f2a30a7edad825dd3424df7e54
|
data/README.md
CHANGED
@@ -134,6 +134,7 @@ In docker as root you must pass the no-sandbox browser option:
|
|
134
134
|
Ferrum::Browser.new(browser_options: { 'no-sandbox': nil })
|
135
135
|
```
|
136
136
|
|
137
|
+
It has also been reported that the Chrome process repeatedly crashes when running inside a Docker container on an M1 Mac preventing Ferrum from working. Ferrum should work as expected when deployed to a Docker container on a non-M1 Mac.
|
137
138
|
|
138
139
|
## Customization
|
139
140
|
|
@@ -144,7 +145,8 @@ Ferrum::Browser.new(options)
|
|
144
145
|
```
|
145
146
|
|
146
147
|
* options `Hash`
|
147
|
-
* `:headless` (Boolean) - Set browser as headless or not, `true` by default.
|
148
|
+
* `:headless` (String | Boolean) - Set browser as headless or not, `true` by default. You can set `"new"` to support
|
149
|
+
[new headless mode](https://developer.chrome.com/articles/new-headless/).
|
148
150
|
* `:xvfb` (Boolean) - Run browser in a virtual framebuffer, `false` by default.
|
149
151
|
* `:window_size` (Array) - The dimensions of the browser window in which to
|
150
152
|
test, expressed as a 2-element array, e.g. [1024, 768]. Default: [1024, 768]
|
@@ -154,7 +156,7 @@ Ferrum::Browser.new(options)
|
|
154
156
|
* `:logger` (Object responding to `puts`) - When present, debug output is
|
155
157
|
written to this object.
|
156
158
|
* `:slowmo` (Integer | Float) - Set a delay in seconds to wait before sending command.
|
157
|
-
|
159
|
+
Useful companion of headless option, so that you have time to see changes.
|
158
160
|
* `:timeout` (Numeric) - The number of seconds we'll wait for a response when
|
159
161
|
communicating with browser. Default is 5.
|
160
162
|
* `:js_errors` (Boolean) - When true, JavaScript errors get re-raised in Ruby.
|
@@ -595,47 +597,49 @@ Activates offline mode for a page.
|
|
595
597
|
|
596
598
|
```ruby
|
597
599
|
browser.network.offline_mode
|
598
|
-
browser.go_to("https://github.com/") # => Ferrum::StatusError (Request to https://github.com/ failed
|
600
|
+
browser.go_to("https://github.com/") # => Ferrum::StatusError (Request to https://github.com/ failed(net::ERR_INTERNET_DISCONNECTED))
|
599
601
|
```
|
600
602
|
|
603
|
+
#### cache(disable: `Boolean`)
|
604
|
+
|
605
|
+
Toggles ignoring cache for each request. If true, cache will not be used.
|
606
|
+
|
607
|
+
```ruby
|
608
|
+
browser.network.cache(disable: true)
|
609
|
+
```
|
601
610
|
|
602
611
|
## Proxy
|
603
612
|
|
604
|
-
You can set a proxy with
|
613
|
+
You can set a proxy with a `:proxy` option:
|
614
|
+
|
615
|
+
```ruby
|
616
|
+
browser = Ferrum::Browser.new(proxy: { host: "x.x.x.x", port: "8800", user: "user", password: "pa$$" })
|
617
|
+
```
|
618
|
+
|
619
|
+
`:bypass` can specify semi-colon-separated list of hosts for which proxy shouldn't be used:
|
605
620
|
|
606
621
|
```ruby
|
607
|
-
browser = Ferrum::Browser.new(proxy: { host: "x.x.x.x", port: "8800" })
|
608
|
-
browser = Ferrum::Browser.new(proxy: { host: "x.x.x.x", port: "8800", user: "user", pasword: "pa$$" })
|
622
|
+
browser = Ferrum::Browser.new(proxy: { host: "x.x.x.x", port: "8800", bypass: "*.google.com;*foo.com" })
|
609
623
|
```
|
610
624
|
|
611
|
-
|
625
|
+
In general passing a proxy option when instantiating a browser results in a browser running with proxy command line
|
626
|
+
flags, so that it affects all pages and contexts. You can create a page in a new context which can use its own proxy
|
627
|
+
settings:
|
612
628
|
|
613
629
|
```ruby
|
614
|
-
browser = Ferrum::Browser.new
|
630
|
+
browser = Ferrum::Browser.new
|
615
631
|
|
616
|
-
browser.
|
617
|
-
browser.create_page(new_context: true) do |page|
|
632
|
+
browser.create_page(proxy: { host: "x.x.x.x", port: 31337, user: "user", password: "password" }) do |page|
|
618
633
|
page.go_to("https://api.ipify.org?format=json")
|
619
634
|
page.body # => "x.x.x.x"
|
620
635
|
end
|
621
636
|
|
622
|
-
browser.
|
623
|
-
browser.create_page(new_context: true) do |page|
|
637
|
+
browser.create_page(proxy: { host: "y.y.y.y", port: 31337, user: "user", password: "password" }) do |page|
|
624
638
|
page.go_to("https://api.ipify.org?format=json")
|
625
639
|
page.body # => "y.y.y.y"
|
626
640
|
end
|
627
641
|
```
|
628
642
|
|
629
|
-
Make sure to create page in the new context, because Chrome doesn't break the connection with the proxy for `CONNECT`
|
630
|
-
requests even if you close the page.
|
631
|
-
|
632
|
-
You can specify semi-colon-separated list of hosts for which proxy shouldn't be used:
|
633
|
-
|
634
|
-
```ruby
|
635
|
-
browser = Ferrum::Browser.new(proxy: { host: "x.x.x.x", port: "8800", bypass: "*.google.com;*foo.com" })
|
636
|
-
browser = Ferrum::Browser.new(proxy: { server: true, bypass: "*.google.com;*foo.com" })
|
637
|
-
```
|
638
|
-
|
639
643
|
|
640
644
|
### Mouse
|
641
645
|
|
@@ -1133,6 +1137,8 @@ frame.at_css("//a[text() = 'Log in']") # => Node
|
|
1133
1137
|
#### evaluate
|
1134
1138
|
#### selected : `Array<Node>`
|
1135
1139
|
#### select
|
1140
|
+
#### scroll_into_view
|
1141
|
+
#### in_viewport?(of: `Node | nil`) : `Boolean`
|
1136
1142
|
|
1137
1143
|
(chainable) Selects options by passed attribute.
|
1138
1144
|
|
@@ -8,11 +8,11 @@ module Ferrum
|
|
8
8
|
class Client
|
9
9
|
INTERRUPTIONS = %w[Fetch.requestPaused Fetch.authRequired].freeze
|
10
10
|
|
11
|
-
def initialize(
|
12
|
-
@
|
11
|
+
def initialize(ws_url, connectable, logger: nil, ws_max_receive_size: nil, id_starts_with: 0)
|
12
|
+
@connectable = connectable
|
13
13
|
@command_id = id_starts_with
|
14
14
|
@pendings = Concurrent::Hash.new
|
15
|
-
@ws = WebSocket.new(ws_url,
|
15
|
+
@ws = WebSocket.new(ws_url, ws_max_receive_size, logger)
|
16
16
|
@subscriber, @interrupter = Subscriber.build(2)
|
17
17
|
|
18
18
|
@thread = Thread.new do
|
@@ -39,7 +39,7 @@ module Ferrum
|
|
39
39
|
message = build_message(method, params)
|
40
40
|
@pendings[message[:id]] = pending
|
41
41
|
@ws.send_message(message)
|
42
|
-
data = pending.value!(@
|
42
|
+
data = pending.value!(@connectable.timeout)
|
43
43
|
@pendings.delete(message[:id])
|
44
44
|
|
45
45
|
raise DeadBrowserError if data.nil? && @ws.messages.closed?
|
@@ -84,7 +84,8 @@ module Ferrum
|
|
84
84
|
case error["message"]
|
85
85
|
# Node has disappeared while we were trying to get it
|
86
86
|
when "No node with given id found",
|
87
|
-
"Could not find node with given id"
|
87
|
+
"Could not find node with given id",
|
88
|
+
"Inspected target navigated or closed"
|
88
89
|
raise NodeNotFoundError, error
|
89
90
|
# Context is lost, page is reloading
|
90
91
|
when "Cannot find context with specified id"
|
@@ -10,7 +10,7 @@ module Ferrum
|
|
10
10
|
# Currently only these browsers support CDP:
|
11
11
|
# https://github.com/cyrus-and/chrome-remote-interface#implementations
|
12
12
|
def self.build(options, user_data_dir)
|
13
|
-
defaults = case options
|
13
|
+
defaults = case options.browser_name
|
14
14
|
when :firefox
|
15
15
|
Options::Firefox.options
|
16
16
|
when :chrome, :opera, :edge, nil
|
@@ -29,14 +29,18 @@ module Ferrum
|
|
29
29
|
@defaults = defaults
|
30
30
|
@options = options
|
31
31
|
@user_data_dir = user_data_dir
|
32
|
-
@path = options
|
32
|
+
@path = options.browser_path || ENV.fetch("BROWSER_PATH", nil) || defaults.detect_path
|
33
33
|
raise BinaryNotFoundError, NOT_FOUND unless @path
|
34
34
|
|
35
35
|
merge_options
|
36
36
|
end
|
37
37
|
|
38
38
|
def xvfb?
|
39
|
-
!!options
|
39
|
+
!!options.xvfb
|
40
|
+
end
|
41
|
+
|
42
|
+
def headless_new?
|
43
|
+
@flags["headless"] == "new"
|
40
44
|
end
|
41
45
|
|
42
46
|
def to_a
|
@@ -47,9 +51,8 @@ module Ferrum
|
|
47
51
|
|
48
52
|
def merge_options
|
49
53
|
@flags = defaults.merge_required(@flags, options, @user_data_dir)
|
50
|
-
@flags = defaults.merge_default(@flags, options) unless options
|
51
|
-
|
52
|
-
@flags.merge!(options.fetch(:browser_options, {}))
|
54
|
+
@flags = defaults.merge_default(@flags, options) unless options.ignore_default_browser_options
|
55
|
+
@flags.merge!(options.browser_options)
|
53
56
|
end
|
54
57
|
end
|
55
58
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Ferrum
|
4
4
|
class Browser
|
5
|
-
|
5
|
+
class Options
|
6
6
|
class Chrome < Base
|
7
7
|
DEFAULT_OPTIONS = {
|
8
8
|
"headless" => nil,
|
@@ -19,8 +19,9 @@ module Ferrum
|
|
19
19
|
"keep-alive-for-test" => nil,
|
20
20
|
"disable-popup-blocking" => nil,
|
21
21
|
"disable-extensions" => nil,
|
22
|
+
"disable-component-extensions-with-background-pages" => nil,
|
22
23
|
"disable-hang-monitor" => nil,
|
23
|
-
"disable-features" => "site-per-process,TranslateUI",
|
24
|
+
"disable-features" => "site-per-process,IsolateOrigins,TranslateUI",
|
24
25
|
"disable-translate" => nil,
|
25
26
|
"disable-background-networking" => nil,
|
26
27
|
"enable-features" => "NetworkService,NetworkServiceInProcess",
|
@@ -32,6 +33,7 @@ module Ferrum
|
|
32
33
|
"disable-ipc-flooding-protection" => nil,
|
33
34
|
"disable-prompt-on-repost" => nil,
|
34
35
|
"disable-renderer-backgrounding" => nil,
|
36
|
+
"disable-site-isolation-trials" => nil,
|
35
37
|
"force-color-profile" => "srgb",
|
36
38
|
"metrics-recording-only" => nil,
|
37
39
|
"safebrowsing-disable-auto-update" => nil,
|
@@ -59,17 +61,27 @@ module Ferrum
|
|
59
61
|
}.freeze
|
60
62
|
|
61
63
|
def merge_required(flags, options, user_data_dir)
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
64
|
+
flags = flags.merge("remote-debugging-port" => options.port,
|
65
|
+
"remote-debugging-address" => options.host,
|
66
|
+
# Doesn't work on MacOS, so we need to set it by CDP
|
67
|
+
"window-size" => options.window_size&.join(","),
|
68
|
+
"user-data-dir" => user_data_dir)
|
69
|
+
|
70
|
+
if options.proxy
|
71
|
+
flags.merge!("proxy-server" => "#{options.proxy[:host]}:#{options.proxy[:port]}")
|
72
|
+
flags.merge!("proxy-bypass-list" => options.proxy[:bypass]) if options.proxy[:bypass]
|
73
|
+
end
|
74
|
+
|
75
|
+
flags
|
69
76
|
end
|
70
77
|
|
71
78
|
def merge_default(flags, options)
|
72
|
-
defaults =
|
79
|
+
defaults = case options.headless
|
80
|
+
when false
|
81
|
+
except("headless", "disable-gpu")
|
82
|
+
when "new"
|
83
|
+
except("headless").merge("headless" => "new")
|
84
|
+
end
|
73
85
|
|
74
86
|
defaults ||= DEFAULT_OPTIONS
|
75
87
|
defaults.merge(flags)
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Ferrum
|
4
4
|
class Browser
|
5
|
-
|
5
|
+
class Options
|
6
6
|
class Firefox < Base
|
7
7
|
DEFAULT_OPTIONS = {
|
8
8
|
"headless" => nil
|
@@ -23,14 +23,11 @@ module Ferrum
|
|
23
23
|
}.freeze
|
24
24
|
|
25
25
|
def merge_required(flags, options, user_data_dir)
|
26
|
-
|
27
|
-
host = options.fetch(:host, BROWSER_HOST)
|
28
|
-
flags.merge("remote-debugger" => "#{host}:#{port}",
|
29
|
-
"profile" => user_data_dir)
|
26
|
+
flags.merge("remote-debugger" => "#{options.host}:#{options.port}", "profile" => user_data_dir)
|
30
27
|
end
|
31
28
|
|
32
29
|
def merge_default(flags, options)
|
33
|
-
defaults = except("headless") unless options.
|
30
|
+
defaults = except("headless") unless options.headless
|
34
31
|
|
35
32
|
defaults ||= DEFAULT_OPTIONS
|
36
33
|
defaults.merge(flags)
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ferrum
|
4
|
+
class Browser
|
5
|
+
class Options
|
6
|
+
HEADLESS = true
|
7
|
+
BROWSER_PORT = "0"
|
8
|
+
BROWSER_HOST = "127.0.0.1"
|
9
|
+
WINDOW_SIZE = [1024, 768].freeze
|
10
|
+
BASE_URL_SCHEMA = %w[http https].freeze
|
11
|
+
DEFAULT_TIMEOUT = ENV.fetch("FERRUM_DEFAULT_TIMEOUT", 5).to_i
|
12
|
+
PROCESS_TIMEOUT = ENV.fetch("FERRUM_PROCESS_TIMEOUT", 10).to_i
|
13
|
+
DEBUG_MODE = !ENV.fetch("FERRUM_DEBUG", nil).nil?
|
14
|
+
|
15
|
+
attr_reader :window_size, :timeout, :logger, :ws_max_receive_size,
|
16
|
+
:js_errors, :base_url, :slowmo, :pending_connection_errors,
|
17
|
+
:url, :env, :process_timeout, :browser_name, :browser_path,
|
18
|
+
:save_path, :extensions, :proxy, :port, :host, :headless,
|
19
|
+
:ignore_default_browser_options, :browser_options, :xvfb
|
20
|
+
|
21
|
+
def initialize(options = nil)
|
22
|
+
@options = Hash(options&.dup)
|
23
|
+
@port = @options.fetch(:port, BROWSER_PORT)
|
24
|
+
@host = @options.fetch(:host, BROWSER_HOST)
|
25
|
+
@timeout = @options.fetch(:timeout, DEFAULT_TIMEOUT)
|
26
|
+
@window_size = @options.fetch(:window_size, WINDOW_SIZE)
|
27
|
+
@js_errors = @options.fetch(:js_errors, false)
|
28
|
+
@headless = @options.fetch(:headless, HEADLESS)
|
29
|
+
@pending_connection_errors = @options.fetch(:pending_connection_errors, true)
|
30
|
+
@process_timeout = @options.fetch(:process_timeout, PROCESS_TIMEOUT)
|
31
|
+
@browser_options = @options.fetch(:browser_options, {})
|
32
|
+
@slowmo = @options[:slowmo].to_f
|
33
|
+
|
34
|
+
@ws_max_receive_size, @env, @browser_name, @browser_path,
|
35
|
+
@save_path, @extensions, @ignore_default_browser_options, @xvfb = @options.values_at(
|
36
|
+
:ws_max_receive_size, :env, :browser_name, :browser_path, :save_path, :extensions,
|
37
|
+
:ignore_default_browser_options, :xvfb
|
38
|
+
)
|
39
|
+
|
40
|
+
@options[:window_size] = @window_size
|
41
|
+
@proxy = parse_proxy(@options[:proxy])
|
42
|
+
@logger = parse_logger(@options[:logger])
|
43
|
+
@base_url = parse_base_url(@options[:base_url]) if @options[:base_url]
|
44
|
+
@url = @options[:url].to_s if @options[:url]
|
45
|
+
|
46
|
+
@options.freeze
|
47
|
+
@browser_options.freeze
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_h
|
51
|
+
@options
|
52
|
+
end
|
53
|
+
|
54
|
+
def parse_base_url(value)
|
55
|
+
parsed = Addressable::URI.parse(value)
|
56
|
+
unless BASE_URL_SCHEMA.include?(parsed&.normalized_scheme)
|
57
|
+
raise ArgumentError, "`base_url` should be absolute and include schema: #{BASE_URL_SCHEMA.join(' | ')}"
|
58
|
+
end
|
59
|
+
|
60
|
+
parsed
|
61
|
+
end
|
62
|
+
|
63
|
+
def parse_proxy(options)
|
64
|
+
return unless options
|
65
|
+
|
66
|
+
raise ArgumentError, "proxy options must be a Hash" unless options.is_a?(Hash)
|
67
|
+
|
68
|
+
if options[:host].nil? && options[:port].nil?
|
69
|
+
raise ArgumentError, "proxy options must be a Hash with at least :host | :port"
|
70
|
+
end
|
71
|
+
|
72
|
+
options
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def parse_logger(logger)
|
78
|
+
return logger if logger
|
79
|
+
|
80
|
+
!logger && DEBUG_MODE ? $stdout.tap { |s| s.sync = true } : logger
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -15,7 +15,6 @@ module Ferrum
|
|
15
15
|
class Process
|
16
16
|
KILL_TIMEOUT = 2
|
17
17
|
WAIT_KILLED = 0.05
|
18
|
-
PROCESS_TIMEOUT = ENV.fetch("FERRUM_PROCESS_TIMEOUT", 10).to_i
|
19
18
|
|
20
19
|
attr_reader :host, :port, :ws_url, :pid, :command,
|
21
20
|
:default_user_agent, :browser_version, :protocol_version,
|
@@ -63,17 +62,17 @@ module Ferrum
|
|
63
62
|
def initialize(options)
|
64
63
|
@pid = @xvfb = @user_data_dir = nil
|
65
64
|
|
66
|
-
if options
|
67
|
-
url = URI.join(options
|
65
|
+
if options.url
|
66
|
+
url = URI.join(options.url, "/json/version")
|
68
67
|
response = JSON.parse(::Net::HTTP.get(url))
|
69
68
|
self.ws_url = response["webSocketDebuggerUrl"]
|
70
69
|
parse_browser_versions
|
71
70
|
return
|
72
71
|
end
|
73
72
|
|
74
|
-
@logger = options
|
75
|
-
@process_timeout = options.
|
76
|
-
@env = Hash(options
|
73
|
+
@logger = options.logger
|
74
|
+
@process_timeout = options.process_timeout
|
75
|
+
@env = Hash(options.env)
|
77
76
|
|
78
77
|
tmpdir = Dir.mktmpdir("ferrum_user_data_dir_")
|
79
78
|
ObjectSpace.define_finalizer(self, self.class.directory_remover(tmpdir))
|
@@ -138,7 +137,7 @@ module Ferrum
|
|
138
137
|
output = ""
|
139
138
|
start = Utils::ElapsedTime.monotonic_time
|
140
139
|
max_time = start + timeout
|
141
|
-
regexp = %r{DevTools listening on (ws://.*)}
|
140
|
+
regexp = %r{DevTools listening on (ws://.*[a-zA-Z0-9-]{36})}
|
142
141
|
while (now = Utils::ElapsedTime.monotonic_time) < max_time
|
143
142
|
begin
|
144
143
|
output += read_io.read_nonblock(512)
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ferrum
|
4
|
+
class Browser
|
5
|
+
#
|
6
|
+
# The browser's version information returned by [Browser.getVersion].
|
7
|
+
#
|
8
|
+
# [Browser.getVersion]: https://chromedevtools.github.io/devtools-protocol/1-3/Browser/#method-getVersion
|
9
|
+
#
|
10
|
+
# @since 0.13
|
11
|
+
#
|
12
|
+
class VersionInfo
|
13
|
+
#
|
14
|
+
# Initializes the browser's version information.
|
15
|
+
#
|
16
|
+
# @param [Hash{String => Object}] properties
|
17
|
+
# The object properties returned by [Browser.getVersion](https://chromedevtools.github.io/devtools-protocol/1-3/Browser/#method-getVersion).
|
18
|
+
#
|
19
|
+
# @api private
|
20
|
+
#
|
21
|
+
def initialize(properties)
|
22
|
+
@properties = properties
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
# The Chrome DevTools protocol version.
|
27
|
+
#
|
28
|
+
# @return [String]
|
29
|
+
#
|
30
|
+
def protocol_version
|
31
|
+
@properties["protocolVersion"]
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# The Chrome version.
|
36
|
+
#
|
37
|
+
# @return [String]
|
38
|
+
#
|
39
|
+
def product
|
40
|
+
@properties["product"]
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
# The Chrome revision properties.
|
45
|
+
#
|
46
|
+
# @return [String]
|
47
|
+
#
|
48
|
+
def revision
|
49
|
+
@properties["revision"]
|
50
|
+
end
|
51
|
+
|
52
|
+
#
|
53
|
+
# The Chrome `User-Agent` string.
|
54
|
+
#
|
55
|
+
# @return [String]
|
56
|
+
#
|
57
|
+
def user_agent
|
58
|
+
@properties["userAgent"]
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# The JavaScript engine version.
|
63
|
+
#
|
64
|
+
# @return [String]
|
65
|
+
#
|
66
|
+
def js_version
|
67
|
+
@properties["jsVersion"]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/ferrum/browser/xvfb.rb
CHANGED
@@ -16,7 +16,7 @@ module Ferrum
|
|
16
16
|
@path = Binary.find("Xvfb")
|
17
17
|
raise BinaryNotFoundError, NOT_FOUND unless @path
|
18
18
|
|
19
|
-
@screen_size = "#{options.
|
19
|
+
@screen_size = "#{options.window_size.join('x')}x24"
|
20
20
|
@display_id = (Time.now.to_f * 1000).to_i % 100_000_000
|
21
21
|
end
|
22
22
|
|