Skip to content

Commit a610938

Browse files
francisbeaudoinroute
authored andcommitted
Handle pending connections losing context on frame navigation
1 parent eb42ed4 commit a610938

File tree

4 files changed

+55
-7
lines changed

4 files changed

+55
-7
lines changed

lib/ferrum/network.rb

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,11 @@ def idle?(connections = 0)
8686
end
8787

8888
def total_connections
89-
@traffic.size
89+
exchange_connections.count
9090
end
9191

9292
def finished_connections
93-
@traffic.count(&:finished?)
93+
exchange_connections.count(&:finished?)
9494
end
9595

9696
def pending_connections
@@ -389,7 +389,10 @@ def subscribe_request_will_be_sent
389389
request.headers.merge!(Hash(exchange.request_extra_info&.dig("headers")))
390390
exchange.request = request
391391

392-
@exchange = exchange if exchange.navigation_request?(@page.main_frame.id)
392+
if exchange.navigation_request?(@page.main_frame.id)
393+
@exchange = exchange
394+
mark_pending_exchanges_as_unknown(exchange)
395+
end
393396
end
394397

395398
@page.on("Network.requestWillBeSentExtraInfo") do |params|
@@ -400,6 +403,17 @@ def subscribe_request_will_be_sent
400403
end
401404
end
402405

406+
# When the main frame navigates Chrome doesn't send `Network.loadingFailed`
407+
# for pending async requests. Therefore, we mark pending connections as unknown since
408+
# they are not relevant to the current navigation.
409+
def mark_pending_exchanges_as_unknown(navigation_exchange)
410+
@traffic.each do |exchange|
411+
break if exchange.id == navigation_exchange.id
412+
413+
exchange.unknown = true if exchange.pending?
414+
end
415+
end
416+
403417
def subscribe_response_received
404418
@page.on("Network.responseReceived") do |params|
405419
exchange = select(params["requestId"]).last
@@ -415,6 +429,8 @@ def subscribe_loading_finished
415429
exchange = select(params["requestId"]).last
416430
next unless exchange
417431

432+
exchange.unknown = false
433+
418434
if (response = exchange.response)
419435
response.loaded = true
420436
response.body_size = params["encodedDataLength"]
@@ -497,5 +513,16 @@ def blacklist?
497513
def whitelist?
498514
Array(@whitelist).any?
499515
end
516+
517+
def exchange_connections
518+
@traffic.select { |e| exchange_connection?(e) }
519+
end
520+
521+
def exchange_connection?(exchange)
522+
return false if !@page.frames.any? { |f| f.id == exchange.request&.frame_id }
523+
return false if exchange.request&.frame_id != @exchange.request&.frame_id
524+
525+
exchange.request&.loader_id == @exchange.request&.loader_id
526+
end
500527
end
501528
end

lib/ferrum/network/exchange.rb

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ class Exchange
2828
# @return [Error, nil]
2929
attr_accessor :error
3030

31+
# Determines if the network exchange is unknown due to
32+
# a lost of its context
33+
#
34+
# @return Boolean
35+
attr_accessor :unknown
36+
3137
# @api private
3238
attr_accessor :request_extra_info
3339

@@ -44,6 +50,7 @@ def initialize(page, id)
4450
@intercepted_request = nil
4551
@request = @response = @error = nil
4652
@request_extra_info = nil
53+
@unknown = false
4754
end
4855

4956
#
@@ -78,12 +85,12 @@ def blocked?
7885

7986
#
8087
# Determines if the request was blocked, a response was returned, or if an
81-
# error occurred.
88+
# error occurred or the exchange is unknown and cannot be inferred.
8289
#
8390
# @return [Boolean]
8491
#
8592
def finished?
86-
blocked? || response&.loaded? || !error.nil? || ping? || blob?
93+
blocked? || response&.loaded? || !error.nil? || ping? || blob? || unknown
8794
end
8895

8996
#
@@ -169,7 +176,8 @@ def inspect
169176
"@intercepted_request=#{@intercepted_request.inspect} " \
170177
"@request=#{@request.inspect} " \
171178
"@response=#{@response.inspect} " \
172-
"@error=#{@error.inspect}>"
179+
"@error=#{@error.inspect}> " \
180+
"@unknown=#{@unknown.inspect}>"
173181
end
174182
end
175183
end

lib/ferrum/network/request.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,15 @@ def frame_id
7171
@params["frameId"]
7272
end
7373

74+
#
75+
# The loader ID of the request.
76+
#
77+
# @return [String]
78+
#
79+
def loader_id
80+
@params["loaderId"]
81+
end
82+
7483
#
7584
# The request timestamp.
7685
#

lib/ferrum/page/frames.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,12 +177,16 @@ def subscribe_execution_context_destroyed
177177
execution_id = params["executionContextId"]
178178
frame = frame_by(execution_id: execution_id)
179179
frame&.execution_id = nil
180+
frame&.state = :stopped_loading
180181
end
181182
end
182183

183184
def subscribe_execution_contexts_cleared
184185
on("Runtime.executionContextsCleared") do
185-
@frames.each_value { |f| f.execution_id = nil }
186+
@frames.each_value do |f|
187+
f.execution_id = nil
188+
f.state = :stopped_loading
189+
end
186190
end
187191
end
188192

0 commit comments

Comments
 (0)