Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion TMWebDriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,19 @@ def handle(self) -> None:
sess.mark_disconnected()
for tab in tabs:
session_id = str(tab['id'])
session_info = {'url': tab.get('url'), 'title': tab.get('title', ''), 'connected_at': time.time(), 'type': 'ext_ws'}
session_info = {
'url': tab.get('url'),
'title': tab.get('title', ''),
'connected_at': time.time(),
'type': 'ext_ws',
'active': bool(tab.get('active')),
'windowId': tab.get('windowId'),
}
sess = driver.sessions.get(session_id)
if sess and sess.is_active(): sess.info = session_info
else: driver._register_client(session_id, self, session_info)
if tab.get('active'):
driver.default_session_id = session_id
elif data.get('type') == 'ack': driver.acks[data.get('id','')] = True
elif data.get('type') == 'result':
driver.results[data.get('id')] = {'success': True, 'data': data.get('result'), 'newTabs': data.get('newTabs', [])}
Expand Down
8 changes: 6 additions & 2 deletions assets/tmwd_cdp_bridge/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ function connectWS() {
const tabs = (await chrome.tabs.query({})).filter(t => isScriptable(t.url));
ws.send(JSON.stringify({
type: 'ext_ready',
tabs: tabs.map(t => ({ id: t.id, url: t.url, title: t.title }))
tabs: tabs.map(t => ({ id: t.id, url: t.url, title: t.title, active: !!t.active, windowId: t.windowId }))
}));
console.log('[TMWD-WS] Sent ext_ready with', tabs.length, 'tabs');
};
Expand Down Expand Up @@ -412,11 +412,15 @@ async function sendTabsUpdate() {
const tabs = (await chrome.tabs.query({})).filter(t => isScriptable(t.url) && !/streamlit/i.test(t.title));
ws.send(JSON.stringify({
type: 'tabs_update',
tabs: tabs.map(t => ({ id: t.id, url: t.url, title: t.title }))
tabs: tabs.map(t => ({ id: t.id, url: t.url, title: t.title, active: !!t.active, windowId: t.windowId }))
}));
}
chrome.tabs.onUpdated.addListener((_, changeInfo) => {
if (changeInfo.status === 'complete') sendTabsUpdate();
});
chrome.tabs.onRemoved.addListener(() => sendTabsUpdate());
chrome.tabs.onCreated.addListener(() => sendTabsUpdate());
chrome.tabs.onActivated.addListener(() => sendTabsUpdate());
if (chrome.windows && chrome.windows.onFocusChanged) {
chrome.windows.onFocusChanged.addListener(() => sendTabsUpdate());
}
25 changes: 25 additions & 0 deletions frontends/tests/test_web_scan_active_tab.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""web_scan should follow the browser's real active tab, not the last operated one."""
from __future__ import annotations

from pathlib import Path

ROOT = Path(__file__).resolve().parent.parent.parent
BRIDGE = (ROOT / "assets" / "tmwd_cdp_bridge" / "background.js").read_text(encoding="utf-8")
DRIVER = (ROOT / "TMWebDriver.py").read_text(encoding="utf-8")
GA = (ROOT / "ga.py").read_text(encoding="utf-8")


def test_bridge_pushes_active_and_listens_for_tab_activation():
assert "active: !!t.active" in BRIDGE
assert "chrome.tabs.onActivated.addListener" in BRIDGE
assert "chrome.windows.onFocusChanged.addListener" in BRIDGE


def test_driver_promotes_active_tab_to_default_session():
assert "if tab.get('active'):" in DRIVER
assert "driver.default_session_id = session_id" in DRIVER
assert "'active': bool(tab.get('active'))" in DRIVER


def test_web_scan_marks_the_active_tab():
assert "sess['active'] = str(sess.get('id')) == str(driver.default_session_id)" in GA
2 changes: 2 additions & 0 deletions ga.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ def web_scan(tabs_only=False, switch_tab_id=None, text_only=False, maxlen=35000)
sess['url'] = sess.get('url', '')[:50] + ("..." if len(sess.get('url', '')) > 50 else "")
tabs.append(sess)
if switch_tab_id: driver.default_session_id = switch_tab_id
for sess in tabs:
sess['active'] = str(sess.get('id')) == str(driver.default_session_id)
result = {
"status": "success",
"metadata": {
Expand Down