electron: [Bug]: webview's document.visibilityState and document.hidden are unreliable

Preflight Checklist

I have read the Contributing Guidelines for this project. I agree to follow the Code of Conduct that this project adheres to. I have searched the issue tracker for a feature request that matches the one I want to file, without success.

Electron Version

11.4.3 - 12.0.4 - 13.0.0-beta.8 - 13.0.0-beta.14

What operating system are you using?

Other Linux

Operating System Version

Fedora, but possibly also happens on other systems

What arch are you using?

x64

Last Known Working Electron version

none

Expected Behavior

Webview hidden/visible state should be directly related to the visibility on the screen. It should also be possible to overwrite the default properties of document.hidden and document.visibilityState with a custom value.

Actual Behavior

It seems to always be visible, even when display is set to none or when the window is minimized. The ONLY way I have currently discovered to make the visibility hidden is by maximizing the window, then minimizing it. After that it will then never switch back to visible again (see screenshot). Though may be there are ways to do it, but overall the API return value doesn’t make any sense most of the time. image “set” is what we toggle the display to, “actual” is document.visibilityState inside the webview after the visibilitychange event fires. document.hidden is linked to visibilityState.

Overall the visibilityState seems extremely unreliable, so much so that I considered this workaround:

document.__defineGetter__("visibilityState", () => "visible")
document.__defineGetter__("hidden", () => false)
​// Or alternatively
Object.defineProperty(document, "hidden", {value: false})
Object.defineProperty(document, "visibilityState", {value: "visible"})

Though even that doesn’t work, because you are not allowed to overwrite this property. I’m considering opening a separate feature request for that, because I don’t think it’s relevant info for every site loaded into a webview to know this and I’m looking for a way to block this API altogether using mock data inside webviews. It would seem that I’m not the only one who would like this functionality.

In 11.4.3 the state is stuck on “visible”, and even when maximized then minimized it doesn’t change at all. For 12.0.4, 13.0.0-beta.8 and 13.0.0-beta.14 the listed flow from the first screenshot is happening, in that it will be stuck on “visible” until that weird trick, after which it’s stuck on “hidden” forever. Though this issue goes much further back, as seen here in 2016, with someone also commenting in 2020 that this is still a problem.

Testcase Gist URL

https://gist.github.com/Jelmerro/37b92f38f767d7942334f218c254cd1d

About this issue

  • Original URL
  • State: open
  • Created 3 years ago
  • Reactions: 5
  • Comments: 18 (4 by maintainers)

Most upvoted comments

Thanks, I know that webkitHidden works, but I want sites to have the correct state under visibilityState and hidden too, as since I cannot overwrite them with contextBridge nor with JS, this is still an issue that needs to be solved.

still an issue, workaround: use document.webkitHidden @Jelmerro

Just to add some background into the issue, I’ve been tracking internal states within the application and apparently visibility is correctly tracked internally. I’ve had 2 webview in separate tabs and was switching between them and on each switch I was sending (for each webview) an ipc message with webcontents id and boolean indicating if it should be hidden based on current visibility or not. And at the moment of sending the event the webcontents webframe was correctly tracking visibilityState as visible when frame was just before to be shown, and hidden when was about to be hidden. After another switch, the values were reversed for the frames, so that’s why I’m confident that internal mechanisms are working correctly.

What I don’t understand is the fact why is the value not properly passed to the chromium webview. Perhaps it’s an internal thing of a chromium instance that does not work for linux systems?

image

image

EDIT: Just tested on the same codebase on windows platform. visibilitychange event is triggered event though the document.visibilityState stays the same.

Perhaps a related ticket: https://github.com/electron/electron/issues/36104

Hi the Electron team ! I encounter a very similar issue, though on my side, document.hidden and the visibilitychange event seems reliable when it comes to minimizing/maximizing the window. The issues starts when playing with the visibility: hidden; css class to handle pseudo-tabbed browsing whithin my Electron app. It does trigger the visibilitychange event every time, but one website I embed uses document.hidden as a predicate, and it is always false when hidding a webview this way.

May we be given an access to an internal renderer API endpoint, which would provides ability to force the document.hidden property ?

Many thanks for your great work !