ferrum 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []