如何让document.hidden始终返回false?Chrome扩展开发求助
问题描述
需要让Google Maps、iCloud等网站的标签页始终处于活跃状态,效果等同于Chrome DevTools → Rendering → Emulate a focused page。目前切换标签的场景已实现,但通过扩展后台刷新标签时,document.hidden仍返回true。尝试阻止visibilitychange事件传播无效,因为后台加载时document.hidden本身就是true。
解决方案
核心思路是重写document的hidden和visibilityState属性,强制返回活跃状态的值,同时拦截相关事件的触发,确保页面脚本无法感知到标签页处于后台。
修改后的扩展代码
manifest.json(保持原配置不变)
{ "manifest_version": 3, "name": "Always visible", "description": "BytE Always visible", "version": "1.4", "host_permissions": [ "*://*/*" ], "permissions": [ "activeTab", "tabs", "webRequest" ], "externally_connectable": { "matches": [ "*://*.google.com/*", "*://*.icloud.com/*", "*://127.0.0.1/*" ] }, "content_scripts": [ { "matches": [ "*://*.google.com/maps/*", "*://*.icloud.com/*", "*://127.0.0.1/*" ], "run_at": "document_start", "js": [ "inject.js" ] } ], "web_accessible_resources": [ { "resources": ["injected.js"], "matches": ["*://*.google.com/*","*://*.icloud.com/*","*://127.0.0.1/*"] } ] }
inject.js(保持原注入逻辑不变)
var s = document.createElement('script'); s.src = chrome.runtime.getURL('injected.js'); s.onload = function() { this.remove(); }; (document.head || document.documentElement).appendChild(s);
injected.js(核心修改部分)
// 重写document.hidden属性,始终返回false Object.defineProperty(document, 'hidden', { get: () => false, configurable: true, enumerable: true }); // 重写document.visibilityState属性,始终返回"visible" Object.defineProperty(document, 'visibilityState', { get: () => 'visible', configurable: true, enumerable: true }); // 拦截所有可见性相关事件,阻止其传播和默认行为 const eventsToBlock = [ 'visibilitychange', 'webkitvisibilitychange', 'blur', 'pagehide', 'webkitpagehide' ]; eventsToBlock.forEach(eventName => { window.addEventListener(eventName, (e) => { e.stopImmediatePropagation(); e.preventDefault(); }, true); }); // 覆盖document.dispatchEvent,阻止可见性事件的触发 const originalDispatch = document.dispatchEvent; document.dispatchEvent = function(event) { if (eventsToBlock.includes(event.type)) { return true; } return originalDispatch.call(this, event); };
测试验证
使用你的测试页面验证效果:
<!DOCTYPE html> <html> <head> <title>Visibility test</title> </head> <body> <pre id="logger"> </pre> <script> var preContent = document.getElementById('logger').innerHTML; var ts = new Date().toISOString(); if (document.hidden) { preContent = preContent + ts + " hidden" + "\n"; } else { preContent = preContent + ts + " visible" + "\n"; } document.getElementById('logger').innerHTML = preContent; document.addEventListener("visibilitychange", () => { var preContent = document.getElementById('logger').innerHTML; var ts = new Date().toISOString(); if (document.hidden) { preContent = preContent + ts + " hidden" + "\n"; } else { preContent = preContent + ts + " visible" + "\n"; } document.getElementById('logger').innerHTML = preContent; }); </script> </body> </html>
后台刷新该测试页面时,日志会始终显示visible,符合需求。
内容的提问来源于stack exchange,提问作者byteflush
相关产品推荐
相关产品推荐

