Class BidiNetworkActivitySource
- All Implemented Interfaces:
AutoCloseable
JavaScriptWaitManager folds
into its existing JS-derived quiet-window engine (issue #3749, Increment B).
Wraps Network (Selenium's org.openqa.selenium.bidi.module.Network) to observe
network.beforeRequestSent, network.responseCompleted, and
network.fetchError events, which today's JS-only marker cannot see at all: worker/
sendBeacon-adjacent traffic issued before SHAFT's monkey-patch runs, requests on
CSP/frozen-prototype pages where the monkey-patch fails to install, etc.
Everything here is advisory, never a hard gate. inFlightCount() can only
extend JavaScriptWaitManager's quiet window the same way a JS marker change does; it is
never compared against zero as a pass/fail condition. This is deliberate: BiDi, unlike the JS
layer, genuinely observes SSE (EventSource) and WebSocket-upgrade requests, which by design stay
"in flight" for the entire page lifetime. Treating inFlightCount() > 0 as a hard
requirement would regress today's tolerance of long-lived connections (the JS layer's
activeRequests simply can't see them) into a wait that never completes.
Lifecycle contract. One instance is created lazily per WebDriver session
(see forDriver(WebDriver)) the first time it is needed, cached for the life of that
session, and torn down via closeAndRemove(WebDriver) during driver teardown. Instances
are only ever constructed when SHAFT.Properties.platform.enableBiDi() is true
and the underlying new Network(driver) call succeeds; new Network(driver)
throws for any session that does not support/enable the BiDi protocol
(see attach(WebDriver)), and construction is never retried for a given driver
instance once it has failed -- the failure is logged once (discretely) and the driver falls back
to the JS-only signal for the rest of its session.
Thread-safety. BiDi event callbacks fire on Selenium's websocket reader thread while
activityMarker()/inFlightCount() are read from the test thread inside
JavaScriptWaitManager's poll loop. All mutable state is therefore
ConcurrentHashMap/Atomic*-backed.
Close discipline. close() only removes the listeners this instance
registered via Network.close(); it never issues a Network.disable-style command
and never touches DevTools/CDP. Per the review-corrected ownership contract for issue #3749, the
DevTools/BiDi session itself is shared and unowned by design -- passive listening never conflicts
with another component's NetworkInterceptor Fetch filter, so the only safe lifecycle rule
is "never disable, only detach your own listeners" (see BrowserNetworkInterceptor for the
analogous CDP-side contract). Note: Selenium 4.46's Network.close() clears the shared
BiDi connection's listeners for the beforeRequestSent/responseStarted/
responseCompleted/authRequired event types outright (not scoped to the calling
instance) and does not clear fetchError listeners at all; harmless here because this
class is the sole registrant of BiDi network.* listeners in SHAFT today, and because
close() is only called from driver teardown, where the whole BiDi connection is about to
go away with the driver regardless.
-
Method Summary
Modifier and TypeMethodDescriptionvoidclose()Detaches this source's listeners from the driver's BiDi connection viaNetwork.close()and marks the source unhealthy.static voidcloseAndRemove(org.openqa.selenium.WebDriver driver) Closes and removes the cachedBidiNetworkActivitySourcefordriver, if one exists.
-
Method Details
-
closeAndRemove
public static void closeAndRemove(org.openqa.selenium.WebDriver driver) Closes and removes the cachedBidiNetworkActivitySourcefordriver, if one exists. Wired into driver teardown (seeDriverFactoryHelper.closeDriver) so a source is never leaked past its driver's session; safe to call even when no source was ever created fordriver(no-op).- Parameters:
driver- the WebDriver session being torn down
-
close
public void close()Detaches this source's listeners from the driver's BiDi connection viaNetwork.close()and marks the source unhealthy. Best-effort: exceptions during close (for example a session that already tore down) are swallowed, matching the driver-teardown close idioms elsewhere in SHAFT (seeBrowserNetworkInterceptor#closeActiveInterceptor).- Specified by:
closein interfaceAutoCloseable
-