Skip to content

Commit 1d0fbae

Browse files
committed
fi: automatic etension wake up
1 parent 907ac6d commit 1d0fbae

File tree

4 files changed

+45
-71
lines changed

4 files changed

+45
-71
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Minimal handshake to wake the MV3 service worker and ensure the WS connect loop runs.
2+
// Fires at document_start on all pages.
3+
(function () {
4+
try {
5+
chrome.runtime.sendMessage({ type: "terminator_content_handshake" }, () => {
6+
// ignore response
7+
});
8+
} catch (_) {
9+
// Ignore if not allowed on special pages
10+
}
11+
})();

terminator/browser-extension/manifest.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@
1010
"host_permissions": [
1111
"<all_urls>"
1212
],
13+
"content_scripts": [
14+
{
15+
"matches": ["<all_urls>"],
16+
"js": ["content.js"],
17+
"run_at": "document_start",
18+
"match_about_blank": true
19+
}
20+
],
1321
"manifest_version": 3,
1422
"name": "Terminator Bridge",
1523
"permissions": [

terminator/browser-extension/worker.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,29 @@ function connect() {
7373
};
7474
}
7575

76+
// Ensure we have an active WS connection on first message from content script
77+
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
78+
try {
79+
if (!message || message.type !== "terminator_content_handshake") return;
80+
log("Received handshake from content script", {
81+
tab: sender.tab && sender.tab.id,
82+
});
83+
// Kick the connector if not already connected; otherwise noop
84+
if (!socket || socket.readyState !== WebSocket.OPEN) {
85+
log("WS not open; attempting connect() due to handshake");
86+
connect();
87+
}
88+
sendResponse({ ok: true });
89+
} catch (e) {
90+
try {
91+
sendResponse({ ok: false, error: String(e && (e.message || e)) });
92+
} catch (_) {}
93+
// swallow
94+
}
95+
// Keep listener alive for async sendResponse
96+
return true;
97+
});
98+
7699
function scheduleReconnect() {
77100
if (reconnectTimer) return;
78101
const delay = currentReconnectDelayMs;

terminator/src/browser_script.rs

Lines changed: 3 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -2,66 +2,10 @@
22
//!
33
//! Simple and clean - just uses the extension bridge, no DevTools fallback.
44
5-
use crate::{AutomationError, Browser, Desktop, Selector, UIElement};
5+
use crate::{AutomationError, Desktop};
66
use std::time::Duration;
77
use tracing::{debug, error, info, warn};
88

9-
async fn wake_extension_service_worker_and_restore_focus(previously_focused: Option<UIElement>) {
10-
// Best-effort: try to open Chrome's extensions page and click the Service Worker link
11-
// Then restore the previously focused UI element to avoid disrupting the user.
12-
let wake_attempt = (|| -> Result<(), AutomationError> {
13-
let desktop = Desktop::new_default()?;
14-
15-
// Open in Chrome explicitly to ensure we're targeting the correct browser settings UI
16-
let _chrome_window = desktop.open_url("chrome://extensions", Some(Browser::Chrome))?;
17-
18-
Ok(())
19-
})();
20-
21-
if wake_attempt.is_err() {
22-
warn!(
23-
error = %wake_attempt.err().unwrap(),
24-
"Failed to open chrome://extensions for service worker wakeup"
25-
);
26-
return;
27-
}
28-
29-
// Give the page a brief moment to render
30-
tokio::time::sleep(Duration::from_millis(800)).await;
31-
32-
// Try a few selector variants that commonly match the service worker inspect link text
33-
// This is intentionally permissive and case-insensitive via contains behavior in matchers.
34-
let candidate_selectors = ["role:link|name:service worker"];
35-
36-
// Best-effort clicking; ignore errors if not found.
37-
if let Ok(desktop) = Desktop::new_default() {
38-
for selector_str in candidate_selectors.iter() {
39-
let try_click = async {
40-
let locator = desktop.locator(Selector::from(*selector_str));
41-
match locator.first(Some(Duration::from_millis(1500))).await {
42-
Ok(link) => link.invoke().map(|_| true).unwrap_or(false),
43-
Err(_) => false,
44-
}
45-
};
46-
47-
if try_click.await {
48-
info!(
49-
selector = *selector_str,
50-
"Clicked service worker link to wake extension"
51-
);
52-
// Allow devtools window to spawn and the worker to initialize
53-
tokio::time::sleep(Duration::from_millis(800)).await;
54-
break;
55-
}
56-
}
57-
}
58-
59-
// Restore original focus to minimize disruption
60-
if let Some(prev) = previously_focused {
61-
let _ = prev.activate_window();
62-
}
63-
}
64-
659
/// Execute JavaScript in browser using extension bridge ONLY
6610
pub async fn execute_script(
6711
browser_element: &crate::UIElement,
@@ -87,10 +31,9 @@ pub async fn execute_script(
8731
let ext = crate::extension_bridge::ExtensionBridge::global().await;
8832
if !ext.is_client_connected().await {
8933
info!("Waiting for extension client to connect...");
90-
// Try a short wait first, then attempt to wake the service worker via extensions UI,
91-
// then continue to wait up to the original overall budget (~60s total)
34+
// Wait up to ~60s total for the client to connect. The MV3 service worker
35+
// will be auto-woken by the content-script handshake on page load/navigation.
9236
let mut connected = false;
93-
let mut attempted_wakeup = false;
9437
for i in 0..120 {
9538
tokio::time::sleep(Duration::from_millis(500)).await;
9639

@@ -100,17 +43,6 @@ pub async fn execute_script(
10043
break;
10144
}
10245

103-
// After ~4 seconds without a connection, try to wake the service worker once
104-
if !attempted_wakeup && i >= 8 {
105-
attempted_wakeup = true;
106-
info!("Attempting to wake extension service worker via chrome://extensions");
107-
wake_extension_service_worker_and_restore_focus(previously_focused.clone()).await;
108-
109-
// Re-focus the browser window to ensure the active tab is correct for evaluation
110-
let _ = browser_element.focus();
111-
tokio::time::sleep(Duration::from_millis(300)).await;
112-
}
113-
11446
if i % 6 == 5 {
11547
info!(
11648
"Still waiting for extension client... {}s",

0 commit comments

Comments
 (0)