Chrome扩展:如何禁用页面可见性API

5t7ly7z5  于 2022-12-16  发布在  Go
关注(0)|答案(2)|浏览(287)

我正在写一个Chrome扩展,需要防止网页触发文档visibilitychange事件。至少我需要能够覆盖文档。visibilityState(即使它是一个只读属性)。如果不可能,因为这个扩展只为我的目的,不会在Chrome扩展商店,有什么方法可以配置我的Chrome浏览器来实现我想要的吗?我只需要在Chrome“开发者模式”打开时使用这个扩展程序,其他时间都不需要。
我希望有人能想出一个创造性的方法来实现这一点。谢谢。
请注意!4年前的一个答案中有一个解决方案,在更新版本的Chrome中不再有效:Spoof or disable the Page Visibility API
亲自测试一下:

// This codes worked 4 years ago but not anymore
var c='(function(){var a=Node.prototype.addEventListener;Node.prototype.addEventListener=function(e){if(e=="visibilitychange"||e=="webkitvisibilitychange"){}else a.apply(this,arguments)}})()'
, E=document.documentElement;
E.setAttribute('onreset', c);
E.dispatchEvent(new CustomEvent('reset'));
E.removeAttribute('onreset');

// THIS WILL STILL LOG THE STATES EVEN WITH THE ABOVE CODE RUNNING
document.addEventListener("visibilitychange", function() {
    console.log( document.visibilityState );
});

如果在Chrome中不可能,有Firefox/Safari/Opera浏览器代码可以实现这一点吗?

s5a0g9ez

s5a0g9ez1#

我的解决方案是:

for (event_name of ["visibilitychange", "webkitvisibilitychange", "blur"]) {
  window.addEventListener(event_name, function(event) {
        event.stopImmediatePropagation();
    }, true);
}

我添加了blur事件,因为我想跳过的视频(everfi. net)使用它来检测我何时切换窗口。将该事件与visibilitychangewebkitvisibilitychange沿着阻止就达到了目的:)
我还修改了扩展的清单,以便它在iframe中工作。

完整代码(chrome扩展名):https://github.com/NavinF/dont

确认使用以下识别牌:

Google Chrome   63.0.3239.132 (Official Build) (64-bit)
Revision    2e6edcfee630baa3775f37cb11796b1603a64360-refs/branch-heads/3239@{#709}
OS  Mac OS X
JavaScript  V8 6.3.292.49
Command Line    /Applications/Google Chrome.app/Contents/MacOS/Google Chrome --flag-switches-begin --flag-switches-end
44u64gxh

44u64gxh2#

我在StackExchange上找到了一个很好的解决方案:

Object.defineProperty(document, 'visibilityState', {value: 'visible', writable: true});
Object.defineProperty(document, 'hidden', {value: false, writable: true});
document.dispatchEvent(new Event("visibilitychange"));

如果有人在使用上述解决方案或本页面中的任何其他解决方案时遇到困难(像我一样),解决方案是将欺骗可见性API的脚本直接添加到DOM中。
在manifest.json中,我添加了以下内容:

"content_scripts": [
    {
      "matches": ["*://*/*"],
      "js": ["disable.js"]
    }
 ]

然后我使用disable.js添加了一个实际操作页面的脚本。

let s = document.createElement("script");
s.setAttribute("id", "yourScriptID");
s.textContent = `
/**
 * Monitors changes to the page visibility.
 */
document.addEventListener('visibilitychange', () => {
  /**
   * Uncomment this line to debug whether the
   * Page Visibility API is being spoofed.
   * console.log('Document.hidden = "${document.hidden}".');
   **/
    Object.defineProperty(document, 'visibilityState', {
        value: 'visible',
        writable: true,
    });
    Object.defineProperty(document, 'hidden', { value: false, writable: true });
  });`;
(document.head || document.documentElement).appendChild(s);

这样做的原因是“内容脚本生活在一个孤立的世界里”
这意味着它们可以访问被注入的页面的DOM,但不能访问该页面创建的任何JavaScript变量或函数。
你会发现下面的讨论对理解内容脚本如何与页面交互以及如何通过扩展安全/正确地注入脚本非常有帮助:
Access variables and functions defined in page context using a content script
姆瓦莱·特赫

相关问题