ferrum 0.1.0

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.
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ferrum
4
+ class Targets
5
+ TARGETS_RETRY_ATTEMPTS = 3
6
+ TARGETS_RETRY_WAIT = 0.001
7
+
8
+ def initialize(browser)
9
+ @page = nil
10
+ @mutex = Mutex.new
11
+ @browser = browser
12
+ @_default = targets.first["targetId"]
13
+
14
+ @browser.on("Target.detachedFromTarget") do |params|
15
+ page = remove_page(params["targetId"])
16
+ page&.close_connection
17
+ end
18
+
19
+ reset
20
+ end
21
+
22
+ def push(target_id, page = nil)
23
+ @targets[target_id] = page
24
+ end
25
+
26
+ def refresh
27
+ @mutex.synchronize do
28
+ targets.each { |t| push(t["targetId"]) if !default?(t) && !has?(t) }
29
+ end
30
+ end
31
+
32
+ def page
33
+ raise NoSuchWindowError unless @page
34
+ @page
35
+ end
36
+
37
+ def window_handle
38
+ page.target_id
39
+ end
40
+
41
+ def window_handles
42
+ @mutex.synchronize { @targets.keys }
43
+ end
44
+
45
+ def switch_to_window(target_id)
46
+ @page = find_or_create_page(target_id)
47
+ end
48
+
49
+ def open_new_window
50
+ target_id = @browser.command("Target.createTarget", url: "about:blank", browserContextId: @_context_id)["targetId"]
51
+ page = Page.new(target_id, @browser, true)
52
+ push(target_id, page)
53
+ target_id
54
+ end
55
+
56
+ def close_window(target_id)
57
+ remove_page(target_id)&.close
58
+ end
59
+
60
+ def within_window(locator)
61
+ original = window_handle
62
+
63
+ if window_handles.include?(locator)
64
+ switch_to_window(locator)
65
+ yield
66
+ else
67
+ raise NoSuchWindowError
68
+ end
69
+ ensure
70
+ switch_to_window(original)
71
+ end
72
+
73
+ def reset
74
+ if @page
75
+ @page.close
76
+ @browser.command("Target.disposeBrowserContext", browserContextId: @_context_id)
77
+ end
78
+
79
+ @page = nil
80
+ @targets = {}
81
+ @_context_id = nil
82
+
83
+ @_context_id = @browser.command("Target.createBrowserContext")["browserContextId"]
84
+ target_id = @browser.command("Target.createTarget", url: "about:blank", browserContextId: @_context_id)["targetId"]
85
+ @page = Page.new(target_id, @browser)
86
+ push(target_id, @page)
87
+ end
88
+
89
+ private
90
+
91
+ def find_or_create_page(target_id)
92
+ page = @targets[target_id]
93
+ page ||= Page.new(target_id, @browser, true)
94
+ @targets[target_id] ||= page
95
+ page
96
+ end
97
+
98
+ def remove_page(target_id)
99
+ page = @targets.delete(target_id)
100
+ @page = nil if page && @page == page
101
+ page
102
+ end
103
+
104
+ def targets
105
+ attempts = 1
106
+ begin
107
+ # Targets cannot be empty the must be at least one default target.
108
+ targets = @browser.command("Target.getTargets")["targetInfos"]
109
+ raise EmptyTargetsError.new("No target browser available") if targets.empty?
110
+ targets
111
+ rescue EmptyTargetsError
112
+ raise if attempts > TARGETS_RETRY_ATTEMPTS
113
+ attempts += 1
114
+ sleep TARGETS_RETRY_WAIT
115
+ retry
116
+ end
117
+ end
118
+
119
+ def default?(target)
120
+ @_default == target["targetId"]
121
+ end
122
+
123
+ def has?(target)
124
+ @targets.key?(target["targetId"])
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ferrum
4
+ VERSION = "0.1.0"
5
+ end
metadata ADDED
@@ -0,0 +1,245 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ferrum
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Dmitry Vorotilin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-08-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: websocket-driver
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0.6'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '0.8'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '0.6'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '0.8'
33
+ - !ruby/object:Gem::Dependency
34
+ name: cliver
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '0.3'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '0.3'
47
+ - !ruby/object:Gem::Dependency
48
+ name: concurrent-ruby
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '1.1'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '1.1'
61
+ - !ruby/object:Gem::Dependency
62
+ name: addressable
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '2.6'
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '2.6'
75
+ - !ruby/object:Gem::Dependency
76
+ name: rake
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '12.3'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '12.3'
89
+ - !ruby/object:Gem::Dependency
90
+ name: rspec
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '3.8'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '3.8'
103
+ - !ruby/object:Gem::Dependency
104
+ name: sinatra
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '2.0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '2.0'
117
+ - !ruby/object:Gem::Dependency
118
+ name: puma
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '4.1'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: '4.1'
131
+ - !ruby/object:Gem::Dependency
132
+ name: byebug
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: '10.0'
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - "~>"
143
+ - !ruby/object:Gem::Version
144
+ version: '10.0'
145
+ - !ruby/object:Gem::Dependency
146
+ name: image_size
147
+ requirement: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - "~>"
150
+ - !ruby/object:Gem::Version
151
+ version: '2.0'
152
+ type: :development
153
+ prerelease: false
154
+ version_requirements: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - "~>"
157
+ - !ruby/object:Gem::Version
158
+ version: '2.0'
159
+ - !ruby/object:Gem::Dependency
160
+ name: pdf-reader
161
+ requirement: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - "~>"
164
+ - !ruby/object:Gem::Version
165
+ version: '2.2'
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - "~>"
171
+ - !ruby/object:Gem::Version
172
+ version: '2.2'
173
+ - !ruby/object:Gem::Dependency
174
+ name: chunky_png
175
+ requirement: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - "~>"
178
+ - !ruby/object:Gem::Version
179
+ version: '1.3'
180
+ type: :development
181
+ prerelease: false
182
+ version_requirements: !ruby/object:Gem::Requirement
183
+ requirements:
184
+ - - "~>"
185
+ - !ruby/object:Gem::Version
186
+ version: '1.3'
187
+ description: Ferrum allows you to control headless Chrome browser
188
+ email:
189
+ - d.vorotilin@gmail.com
190
+ executables: []
191
+ extensions: []
192
+ extra_rdoc_files: []
193
+ files:
194
+ - LICENSE
195
+ - README.md
196
+ - lib/ferrum.rb
197
+ - lib/ferrum/browser.rb
198
+ - lib/ferrum/browser/api.rb
199
+ - lib/ferrum/browser/api/cookie.rb
200
+ - lib/ferrum/browser/api/header.rb
201
+ - lib/ferrum/browser/api/intercept.rb
202
+ - lib/ferrum/browser/api/screenshot.rb
203
+ - lib/ferrum/browser/client.rb
204
+ - lib/ferrum/browser/process.rb
205
+ - lib/ferrum/browser/subscriber.rb
206
+ - lib/ferrum/browser/web_socket.rb
207
+ - lib/ferrum/cookie.rb
208
+ - lib/ferrum/errors.rb
209
+ - lib/ferrum/network/error.rb
210
+ - lib/ferrum/network/request.rb
211
+ - lib/ferrum/network/response.rb
212
+ - lib/ferrum/node.rb
213
+ - lib/ferrum/page.rb
214
+ - lib/ferrum/page/dom.rb
215
+ - lib/ferrum/page/frame.rb
216
+ - lib/ferrum/page/input.json
217
+ - lib/ferrum/page/input.rb
218
+ - lib/ferrum/page/net.rb
219
+ - lib/ferrum/page/runtime.rb
220
+ - lib/ferrum/targets.rb
221
+ - lib/ferrum/version.rb
222
+ homepage: https://github.com/route/ferrum
223
+ licenses:
224
+ - MIT
225
+ metadata: {}
226
+ post_install_message:
227
+ rdoc_options: []
228
+ require_paths:
229
+ - lib
230
+ required_ruby_version: !ruby/object:Gem::Requirement
231
+ requirements:
232
+ - - ">="
233
+ - !ruby/object:Gem::Version
234
+ version: 2.3.0
235
+ required_rubygems_version: !ruby/object:Gem::Requirement
236
+ requirements:
237
+ - - ">="
238
+ - !ruby/object:Gem::Version
239
+ version: '0'
240
+ requirements: []
241
+ rubygems_version: 3.0.3
242
+ signing_key:
243
+ specification_version: 4
244
+ summary: Ruby headless Chrome driver
245
+ test_files: []