ask-web-fetch 0.5.7 → 0.5.8
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/lib/ask/web_fetch/backends/attached_browser.rb +55 -2
- data/lib/ask/web_fetch/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d3e0494d6f9fd54b7b80b667b97d57f17d1b0e871d44c26fada9ad91669a391d
|
|
4
|
+
data.tar.gz: e06918a4ca162ee2111715530f67ab68c8feae529c27c180cebb0cf462f13867
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4a045bb9226bb302cd60bda942acfa05a00e1f3d1aced99edc3bbd77a061c7650580b40447c385a4777b7156fa81aa0fcc57267caa4385b478e4d005c015f41f
|
|
7
|
+
data.tar.gz: ffab19b64968c909c67dd631902b447738248c7e6a0d3da5db8851cc2ff615ec627bc8a89407b40dbeabbebb591d2cd6726c21747de34962cc9ff77c98ce16e8
|
|
@@ -27,7 +27,11 @@ module Ask
|
|
|
27
27
|
|
|
28
28
|
# Creates a page as a fresh tab in the attached browser.
|
|
29
29
|
def create_page
|
|
30
|
-
|
|
30
|
+
# Capture the frontmost app once per browser instance, not per
|
|
31
|
+
# page: a batch of fetches steals focus once and restores to the
|
|
32
|
+
# same app, and consecutive fetches don't fight each other.
|
|
33
|
+
@frontmost_app ||= FocusRestorer.capture_frontmost
|
|
34
|
+
Page.new(client, timeout: @timeout, restore_focus_to: @frontmost_app)
|
|
31
35
|
end
|
|
32
36
|
|
|
33
37
|
private
|
|
@@ -43,9 +47,10 @@ module Ask
|
|
|
43
47
|
# enough CDP for the Browser backend: navigate, read title/URL/HTML,
|
|
44
48
|
# and report the main-document HTTP status.
|
|
45
49
|
class Page
|
|
46
|
-
def initialize(client, timeout:)
|
|
50
|
+
def initialize(client, timeout:, restore_focus_to: nil)
|
|
47
51
|
@client = client
|
|
48
52
|
@timeout = timeout
|
|
53
|
+
@restore_focus_to = restore_focus_to
|
|
49
54
|
@target_id = @client.command('Target.createTarget', url: 'about:blank')['targetId']
|
|
50
55
|
@session = @client.session(
|
|
51
56
|
@client.command('Target.attachToTarget', targetId: @target_id, flatten: true)['sessionId']
|
|
@@ -91,6 +96,12 @@ module Ask
|
|
|
91
96
|
@client.command('Target.closeTarget', targetId: @target_id)
|
|
92
97
|
rescue Ferrum::Error
|
|
93
98
|
nil
|
|
99
|
+
ensure
|
|
100
|
+
# The attached dev Chrome window steals focus when a tab is
|
|
101
|
+
# created; give it back once the tab is gone — but only to an
|
|
102
|
+
# app that ISN'T Chrome, so a fetch while the user is already
|
|
103
|
+
# looking at Chrome doesn't ping-pong.
|
|
104
|
+
FocusRestorer.restore_frontmost(@restore_focus_to)
|
|
94
105
|
end
|
|
95
106
|
|
|
96
107
|
def evaluate(expression)
|
|
@@ -189,6 +200,48 @@ module Ask
|
|
|
189
200
|
end
|
|
190
201
|
end
|
|
191
202
|
end
|
|
203
|
+
|
|
204
|
+
# macOS dev convenience: the attached Chrome window steals focus when
|
|
205
|
+
# a tab is created, and a developer working in another app wants it
|
|
206
|
+
# back once the tab is closed. Captures the frontmost app before the
|
|
207
|
+
# page is created and re-activates it after close. Deliberately
|
|
208
|
+
# cheap and quiet: one osascript each way, rescued to nil everywhere
|
|
209
|
+
# else (prod is headless Linux — this module is a no-op there, and
|
|
210
|
+
# even on macOS a failure must never fail a fetch).
|
|
211
|
+
module FocusRestorer
|
|
212
|
+
# The command runner, injectable for tests (minitest 6 ships no
|
|
213
|
+
# mock support, so tests swap this instead of stubbing).
|
|
214
|
+
class << self
|
|
215
|
+
attr_writer :runner
|
|
216
|
+
|
|
217
|
+
def runner
|
|
218
|
+
@runner ||= method(:system)
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def self.capture_frontmost
|
|
223
|
+
return nil unless RUBY_PLATFORM.include?('darwin')
|
|
224
|
+
|
|
225
|
+
out = `osascript -e 'tell application "System Events" to get name of first application process whose frontmost is true' 2>/dev/null`.strip
|
|
226
|
+
out.empty? ? nil : out
|
|
227
|
+
rescue StandardError
|
|
228
|
+
nil
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def self.restore_frontmost(app)
|
|
232
|
+
return if app.nil? || app.empty?
|
|
233
|
+
|
|
234
|
+
# Never ping-pong: if the user is already looking at Chrome (or
|
|
235
|
+
# headless/CI has no frontmost app at all), there's nothing to
|
|
236
|
+
# give back.
|
|
237
|
+
return if app == 'Google Chrome'
|
|
238
|
+
|
|
239
|
+
runner.call("osascript -e 'tell application \"#{app}\" to activate' 2>/dev/null")
|
|
240
|
+
nil
|
|
241
|
+
rescue StandardError
|
|
242
|
+
nil
|
|
243
|
+
end
|
|
244
|
+
end
|
|
192
245
|
end
|
|
193
246
|
end
|
|
194
247
|
end
|