You'll need to run your code in the MAIN world of the page by declaring "world": "MAIN" and "run_at": "document_start" for the content script. The script will use Object.defineProperty to override `visibilityState` (value) and `onvisibilitychange` (getter and setter) properties on `document`, also use `Proxy` to override `document.addEventListener` if that's what the webpage is using or `EventTarget.prototype.addEventListener` if you don't know for sure. The Proxy's `apply` handler will do nothing if the first argument is "visibilitychange", otherwise it'll call the inherited addEventListener.
There is also the problem of the browser itself pausing the timers in backgrounded tabs, so you'll have to override `setTimeout`, `setInterval`, `clearTimeout`, `clearInterval` on `window` to make them send a message to the extension, which will call the corresponding function in its background script and send a message back when done. Since there may be tons of such messages, use chrome.runtime.connect to establish a long-lived communication channel.