ferrum 0.12 → 0.14
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|