refactor: remove detect_newtab, use session dict diff for new tab detection

This commit is contained in:
Liang Jiaqing
2026-02-25 08:47:02 +08:00
parent 708ffb3248
commit 83167e47a6
4 changed files with 21 additions and 43 deletions

View File

@@ -93,9 +93,8 @@ class TMWebDriver:
session_id = data.get('sessionId') session_id = data.get('sessionId')
code = data.get('code') code = data.get('code')
timeout = float(data.get('timeout', 10.0)) timeout = float(data.get('timeout', 10.0))
detect_newtab = data.get('detect_newtab', False)
try: try:
result = self.execute_js(code, timeout=timeout, session_id=session_id, detect_newtab=detect_newtab) result = self.execute_js(code, timeout=timeout, session_id=session_id)
print('[remote result]', (str(code)[:50] + ' RESULT:' +str(result)[:50]).replace('\n', ' ')) print('[remote result]', (str(code)[:50] + ' RESULT:' +str(result)[:50]).replace('\n', ' '))
return json.dumps({'r': result}, ensure_ascii=False) return json.dumps({'r': result}, ensure_ascii=False)
except Exception as e: except Exception as e:
@@ -168,13 +167,12 @@ class TMWebDriver:
session.mark_disconnected() session.mark_disconnected()
break break
def execute_js(self, code, timeout=15, session_id=None, detect_newtab=False) -> Any: def execute_js(self, code, timeout=15, session_id=None) -> Any:
if session_id is None: session_id = self.default_session_id if session_id is None: session_id = self.default_session_id
if self.is_remote: if self.is_remote:
print('remote_execute_js') print('remote_execute_js')
response = self._remote_cmd({"cmd": "execute_js", "sessionId": session_id, response = self._remote_cmd({"cmd": "execute_js", "sessionId": session_id,
"code": code, "timeout": str(timeout), "code": code, "timeout": str(timeout)}).get('r', {})
"detect_newtab": detect_newtab}).get('r', {})
if response.get('error'): raise Exception(response['error']) if response.get('error'): raise Exception(response['error'])
return response return response
@@ -194,7 +192,7 @@ class TMWebDriver:
tp = session.type tp = session.type
assert tp in ['ws', 'http'], f"Unsupported session type: {tp}" assert tp in ['ws', 'http'], f"Unsupported session type: {tp}"
exec_id = str(uuid.uuid4()) exec_id = str(uuid.uuid4())
payload = json.dumps({'id': exec_id, 'code': code, 'detect_newtab': detect_newtab}) payload = json.dumps({'id': exec_id, 'code': code})
if tp == 'ws': session.ws_client.send_message(payload) if tp == 'ws': session.ws_client.send_message(payload)
elif tp == 'http': session.http_queue.put(payload) elif tp == 'http': session.http_queue.put(payload)
@@ -265,7 +263,7 @@ class TMWebDriver:
def jump(self, url, timeout=10): self.execute_js(f"window.location.href='{url}'", timeout=timeout) def jump(self, url, timeout=10): self.execute_js(f"window.location.href='{url}'", timeout=timeout)
def newtab(self, url=None): def newtab(self, url=None):
if url is None: url = "http://www.baidu.com/robots.txt" if url is None: url = "http://www.baidu.com/robots.txt"
return self.execute_js(f'GM_openInTab("{url}");', detect_newtab=True) return self.execute_js(f'GM_openInTab("{url}");')
if __name__ == "__main__": if __name__ == "__main__":
driver = TMWebDriver(host='localhost', port=18765) driver = TMWebDriver(host='localhost', port=18765)

View File

@@ -57,14 +57,6 @@
console.log(log_prefix + `使用现有会话ID: ${sid}`); console.log(log_prefix + `使用现有会话ID: ${sid}`);
} }
try {
GM_setValue('new_tab_report', {
url: window.location.href,
sessionId: sid,
ts: Date.now()
});
} catch (e) {}
// 保存会话ID // 保存会话ID
GM_setValue('sid', sid); GM_setValue('sid', sid);
@@ -374,33 +366,17 @@
try { try {
let data = JSON.parse(e.data); let data = JSON.parse(e.data);
ws.send(JSON.stringify({type: 'ack',id: data.id})); ws.send(JSON.stringify({type: 'ack',id: data.id}));
let startTime = Date.now();
let newTabs = [];
let checkNewTab = data.detect_newtab === true;
GM_setValue('new_tab_report', null);
const response = executeCode(data); const response = executeCode(data);
if (response.error) { if (response.error) {
handleError(data.id, response.error, '执行代码'); handleError(data.id, response.error, '执行代码');
} else { } else {
if (checkNewTab) {
for (let i = 0; i < 10; i++) {
await new Promise(r => setTimeout(r, 150));
let latestReport = GM_getValue('new_tab_report');
if (latestReport && latestReport.ts >= startTime) {
console.log(`%c[Detected] 轮询第 ${i+1} 次抓到新标签!`, "color: green");
newTabs.push(latestReport);
break;
}
}
}
updateStatus('ok'); updateStatus('ok');
ws.send(JSON.stringify({ ws.send(JSON.stringify({
type: 'result', type: 'result',
id: data.id, id: data.id,
sessionId: sid, sessionId: sid,
result: response.result, result: response.result
newTabs: newTabs
})); }));
} }
} catch (parseError) { } catch (parseError) {

View File

@@ -36,6 +36,12 @@ fetch('PDF_URL').then(r=>r.blob()).then(b=>{
``` ```
注意需同源或CORS允许跨域先导航到目标域再执行 注意需同源或CORS允许跨域先导航到目标域再执行
## Chrome后台标签节流
- 后台标签中`setTimeout`被Chrome intensive throttling延迟到≥1min/次
- TM脚本中detect_newtab的轮询(`setTimeout 150ms × 10`)会超时
- 已修复移除TM脚本内轮询改由Python侧`get_session_dict()`前后对比检测新标签
- 同理TM脚本中任何后台逻辑都应避免依赖setTimeout轮询
## Cookie提取(含HttpOnly) ## Cookie提取(含HttpOnly)
前提:需先安装`assets/cookie_grabber/`扩展 前提:需先安装`assets/cookie_grabber/`扩展
机制:注入`id="__ljqcg__"`的div→扩展检测后自动将完整cookie写回该元素textContent含HttpOnly 机制:注入`id="__ljqcg__"`的div→扩展检测后自动将完整cookie写回该元素textContent含HttpOnly

View File

@@ -862,13 +862,12 @@ def get_html(driver, cutlist=False, maxchars=28000, instruction="", extra_js="")
def execute_js_rich(script, driver): def execute_js_rich(script, driver):
try: last_html = get_html(driver, cutlist=False, extra_js=temp_monitor_js) try: last_html = get_html(driver, cutlist=False, extra_js=temp_monitor_js)
except: last_html = None except: last_html = None
result = None; error_msg = None; newTabs = []; reloaded = False result = None; error_msg = None; reloaded = False
before_sids = set(driver.get_session_dict().keys()) before_sids = set(driver.get_session_dict().keys())
try: try:
print(f"Executing: {script[:250]} ...") print(f"Executing: {script[:250]} ...")
response = driver.execute_js(script, detect_newtab=True) response = driver.execute_js(script)
result = response.get('data') or response.get('result') result = response.get('data') or response.get('result')
newTabs = response.get('newTabs', [])
if response.get('closed', 0) == 1: reloaded = True if response.get('closed', 0) == 1: reloaded = True
time.sleep(2) time.sleep(2)
except Exception as e: except Exception as e:
@@ -879,16 +878,15 @@ def execute_js_rich(script, driver):
rr = { rr = {
"status": "failed" if error_msg else "success", "status": "failed" if error_msg else "success",
"js_return": result, "js_return": result,
"environment": {"newTabs": newTabs, "reloaded": reloaded}, "environment": {"reloaded": reloaded},
"tab_id": driver.default_session_id "tab_id": driver.default_session_id
} }
if reloaded and len(newTabs) == 0: after = driver.get_session_dict()
after = driver.get_session_dict() new_sids = {k: v for k, v in after.items() if k not in before_sids}
new_sids = {k: v for k, v in after.items() if k not in before_sids} if new_sids:
if new_sids: newTabs = [{'id': k, 'url': v} for k, v in new_sids.items()]
newTabs = [{'id': k, 'url': v} for k, v in new_sids.items()] rr['environment']['newTabs'] = newTabs
rr['environment']['newTabs'] = newTabs rr['suggestion'] = "页面已刷新,以上新标签页在执行期间连接。"
rr['suggestion'] = "页面已刷新,以上新标签页在执行期间连接。"
if error_msg: rr['error'] = error_msg if error_msg: rr['error'] = error_msg
if not reloaded: if not reloaded:
try: rr['transients'] = get_temp_texts(driver) try: rr['transients'] = get_temp_texts(driver)