feat(callback_host): close helper page on Drop via browser WS
🤖 Generated with [Qoder][https://qoder.com]
This commit is contained in:
@@ -324,6 +324,13 @@ impl BrowserCallbackExecutor for LiveBrowserCallbackHost {
|
|||||||
|
|
||||||
impl Drop for LiveBrowserCallbackHost {
|
impl Drop for LiveBrowserCallbackHost {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
|
// Best-effort: tell the browser to close the helper page tab.
|
||||||
|
close_helper_page(
|
||||||
|
&self.browser_ws_url,
|
||||||
|
self.host.helper_url(),
|
||||||
|
self.use_hidden_domain,
|
||||||
|
);
|
||||||
|
|
||||||
self.shutdown.store(true, Ordering::Relaxed);
|
self.shutdown.store(true, Ordering::Relaxed);
|
||||||
if let Some(handle) = self.server_thread.lock().unwrap().take() {
|
if let Some(handle) = self.server_thread.lock().unwrap().take() {
|
||||||
let _ = handle.join();
|
let _ = handle.join();
|
||||||
@@ -373,6 +380,46 @@ fn bootstrap_helper_page(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Best-effort attempt to close the helper page tab via browser WebSocket.
|
||||||
|
/// Silently ignores all errors — this runs during Drop and must not panic.
|
||||||
|
fn close_helper_page(browser_ws_url: &str, helper_url: &str, use_hidden_domain: bool) {
|
||||||
|
let close_action = if use_hidden_domain {
|
||||||
|
"sgHideBrowerserClosePage"
|
||||||
|
} else {
|
||||||
|
"sgBrowserClosePage"
|
||||||
|
};
|
||||||
|
|
||||||
|
let result: Result<(), Box<dyn std::error::Error>> = (|| {
|
||||||
|
// Use a raw TcpStream with timeouts instead of tungstenite::connect
|
||||||
|
// which does not expose a connection timeout.
|
||||||
|
let addr = browser_ws_url
|
||||||
|
.trim_start_matches("ws://")
|
||||||
|
.trim_start_matches("wss://");
|
||||||
|
let stream = TcpStream::connect_timeout(
|
||||||
|
&addr.parse().map_err(|e| format!("addr parse: {e}"))?,
|
||||||
|
Duration::from_millis(100),
|
||||||
|
)?;
|
||||||
|
stream.set_read_timeout(Some(Duration::from_millis(200)))?;
|
||||||
|
stream.set_write_timeout(Some(Duration::from_millis(200)))?;
|
||||||
|
let (mut websocket, _) = tungstenite::client(
|
||||||
|
browser_ws_url,
|
||||||
|
stream,
|
||||||
|
)?;
|
||||||
|
websocket.send(Message::Text(
|
||||||
|
r#"{"type":"register","role":"web"}"#.to_string().into(),
|
||||||
|
))?;
|
||||||
|
// Drain the welcome prelude (best-effort, ignore timeout).
|
||||||
|
let _ = websocket.read();
|
||||||
|
let payload = json!([helper_url, close_action, helper_url]).to_string();
|
||||||
|
websocket.send(Message::Text(payload.into()))?;
|
||||||
|
Ok(())
|
||||||
|
})();
|
||||||
|
|
||||||
|
if let Err(err) = result {
|
||||||
|
eprintln!("close_helper_page best-effort failed (harmless): {err}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn recv_bootstrap_prelude(
|
fn recv_bootstrap_prelude(
|
||||||
websocket: &mut tungstenite::WebSocket<tungstenite::stream::MaybeTlsStream<TcpStream>>,
|
websocket: &mut tungstenite::WebSocket<tungstenite::stream::MaybeTlsStream<TcpStream>>,
|
||||||
) -> Result<(), PipeError> {
|
) -> Result<(), PipeError> {
|
||||||
|
|||||||
Reference in New Issue
Block a user