Class BrowserBoot
Browser through its load + readiness + retry lifecycle.The SWT Browser widget on the Edge/WebView2 backend (Windows 11) does not finish initializing until its control hierarchy is actually visible on screen. A setUrl (or setText) issued before that moment can be silently dropped: the page never loads, the injected BrowserFunction bridge never becomes live, and any JavaScript→Java readiness callback the site waits for never fires. The browser cell sits blank. Re-issuing the navigation (a manual "Reload") always fixes it, because by then the control is visible.
BrowserBoot centralizes that lifecycle: it owns the readiness handshake, the gated/retrying load, the file: URL pre-validation, and (via the create(org.eclipse.swt.widgets.Composite, org.eclipse.swt.graphics.Color, java.util.function.Consumer<org.eclipse.swt.browser.Browser>, java.util.function.Consumer<org.eclipse.swt.browser.Browser>) factory) creation-failure handling. The site continues to register its own other BrowserFunctions directly on the browser; BrowserBoot does not wrap or manage those.
Two distinct readiness moments are exposed, both as nullable Consumer<Browser>:
onBridge— fires when the readinessBrowserFunctionis called from the page (JS→Java confirmed). Most sites passnullhere.onReady— fires once, on the UI thread, when the browser is REALLY ready, meaning BOTH the readinessBrowserFunctionhas fired (JS→Java works) ANDProgressListener.completed(org.eclipse.swt.browser.ProgressEvent)has fired (Java→JS into the loaded page works).
CRITICAL: the retry (re-issuing the load) is gated on the readiness BrowserFunction having fired ONLY, never on completed. The original hang was the SWT BrowserFunctions never being injected into the page at all; in that hang completed can still fire (the document loaded) while the bridge is dead, so gating retry on completed would fail to retry the actual hang. The BrowserFunction firing proves injection succeeded, which is the correct retry-stop signal.
All callbacks run on the SWT UI thread (BrowserFunction callbacks and timerExec are UI-thread by SWT contract), so the per-instance state needs no synchronization.
- Author:
- Christopher Mindus
Method Summary
Modifier and TypeMethodDescriptionstatic BrowserBootWraps an already-createdBrowser(escape hatch for sites that create and manage their own browser, e.g.static BrowserBootCreates a browser viaSWTHelper.createBrowserOrCompositeForFailure(org.eclipse.swt.widgets.Composite, org.eclipse.swt.graphics.Color)and wraps it.Returns theBrowser, or null if creation failed.Returns what is actually in the layout: theBrowser, or the fallback error Composite.booleanReturns whether a realBrowserwas created.voidIssues a gated, validated, retryingsetUrl.voidIssues a gated, retryingsetText.Sets theonBridgecallback (alternative to passing it tocreate(org.eclipse.swt.widgets.Composite, org.eclipse.swt.graphics.Color, java.util.function.Consumer<org.eclipse.swt.browser.Browser>, java.util.function.Consumer<org.eclipse.swt.browser.Browser>)/attach(org.eclipse.swt.browser.Browser, java.util.function.Consumer<org.eclipse.swt.browser.Browser>, java.util.function.Consumer<org.eclipse.swt.browser.Browser>)).Sets theonReadycallback (alternative to passing it tocreate(org.eclipse.swt.widgets.Composite, org.eclipse.swt.graphics.Color, java.util.function.Consumer<org.eclipse.swt.browser.Browser>, java.util.function.Consumer<org.eclipse.swt.browser.Browser>)/attach(org.eclipse.swt.browser.Browser, java.util.function.Consumer<org.eclipse.swt.browser.Browser>, java.util.function.Consumer<org.eclipse.swt.browser.Browser>)).readyFunction(String name) Registers the readinessBrowserFunction— the JS→Java half of the handshake.
Method Details
create
public static BrowserBoot create(Composite parent, Color background, Consumer<Browser> onBridge, Consumer<Browser> onReady) Creates a browser viaSWTHelper.createBrowserOrCompositeForFailure(org.eclipse.swt.widgets.Composite, org.eclipse.swt.graphics.Color)and wraps it.The factory ALWAYS returns a
BrowserBoot(never null). When browser creation fails (e.g. Windows GDI/USER handle exhaustion) the wrapped component is a read-only fallback Composite showing the exception, andisBrowser()returns false. The caller lays outgetComponent()(the browser OR the error UI) and only callsload(java.lang.String)whenisBrowser()is true.onReadyonly ever fires when there IS a browser.- Parameters:
parent- The parent composite.background- The background color, nullable.onBridge- Fires when the readiness function fires; nullable.onReady- Fires once when really ready; nullable.- Returns:
- A new
BrowserBoot, never null.
attach
public static BrowserBoot attach(Browser browser, Consumer<Browser> onBridge, Consumer<Browser> onReady) Wraps an already-createdBrowser(escape hatch for sites that create and manage their own browser, e.g. the tooltip's measure-then-show flow).- Parameters:
browser- The browser to drive; not null.onBridge- Fires when the readiness function fires; nullable.onReady- Fires once when really ready; nullable.- Returns:
- A new
BrowserBoot, never null.
isBrowser
public boolean isBrowser()Returns whether a realBrowserwas created.- Returns:
- true if a Browser is present, false if creation failed (fallback Composite).
getBrowser
Returns theBrowser, or null if creation failed.- Returns:
- The Browser, or null.
getComponent
Returns what is actually in the layout: theBrowser, or the fallback error Composite. Never null. The caller sets layout data on THIS.- Returns:
- The component to lay out, never null.
readyFunction
Registers the readinessBrowserFunction— the JS→Java half of the handshake.When the page calls this function (from its DOM-ready/init handler),
BrowserBootmarks the bridge as fired, invokesonBridge(if non-null) and, ifcompletedhas also fired, latchesreadyand runsonReadyonce. The name varies by site — pass the exact string the page JS calls (e.g."onJSInitialized").If browser creation failed (no browser), this is a silent no-op: creation failure is a designed, queryable state (see
isBrowser()), not an error. A disposed browser or a second registration are programming errors and throwIllegalStateException.- Parameters:
name- The readiness function name as called by the page.- Returns:
- This
BrowserBoot, for chaining. - Throws:
IllegalStateException- if the browser is disposed, or the readiness function has already been registered.
onBridge
Sets theonBridgecallback (alternative to passing it tocreate(org.eclipse.swt.widgets.Composite, org.eclipse.swt.graphics.Color, java.util.function.Consumer<org.eclipse.swt.browser.Browser>, java.util.function.Consumer<org.eclipse.swt.browser.Browser>)/attach(org.eclipse.swt.browser.Browser, java.util.function.Consumer<org.eclipse.swt.browser.Browser>, java.util.function.Consumer<org.eclipse.swt.browser.Browser>)).- Parameters:
onBridge- Fires when the readiness function fires; nullable.- Returns:
- This
BrowserBoot, for chaining.
onReady
Sets theonReadycallback (alternative to passing it tocreate(org.eclipse.swt.widgets.Composite, org.eclipse.swt.graphics.Color, java.util.function.Consumer<org.eclipse.swt.browser.Browser>, java.util.function.Consumer<org.eclipse.swt.browser.Browser>)/attach(org.eclipse.swt.browser.Browser, java.util.function.Consumer<org.eclipse.swt.browser.Browser>, java.util.function.Consumer<org.eclipse.swt.browser.Browser>)).- Parameters:
onReady- Fires once when really ready; nullable.- Returns:
- This
BrowserBoot, for chaining.
load
Issues a gated, validated, retryingsetUrl.For a
file:URL the target is pre-validated: if the file is confirmed missing/unreadable, a clear error is logged and the retry loop is NOT entered (retrying a non-existent file is pointless). If the URL cannot be parsed to a file, the pre-check fails open and the load proceeds. Non-file schemes (http/https/about/data) are never pre-checked — a transient (e.g. a still-starting localhost server) is exactly what the retry is for. No-op if there is no browser.- Parameters:
url- The URL to load.
loadText
Issues a gated, retryingsetText. Same asload(java.lang.String)but with HTML and no file pre-check. No-op if there is no browser.- Parameters:
html- The HTML to load.