Firefox turns out to need some degree of 'autoplay' support

May 6, 2018

When I wrote some notes about Firefox's current media autoplay settings, I said, about the central function in Firefox that decides whether or not media can autoplay:

Since I don't want videos to ever autoplay, [...] I may someday try making the entire function just immediately return false.

I did this experiment and I can now report that the result is a failure. Completely disabling IsMediaElementAllowedToPlay() from AutoplayPolicy.cpp, ie making it always return false, results in a Firefox that won't play video at all. It won't play YouTube videos, which doesn't entirely surprise me, but it also won't even play directly loaded .mp4 files. The videos load, but clicking on the appropriate 'play' button or control does nothing and the video never starts going.

I wasn't entirely surprised about this for YouTube, because I assume that YouTube is wrapping the raw video in a JavaScript player that controls a bunch of things, inserts ads, and so on. With a surrounding JS player it's presumably ultimately the JS player that is telling Firefox to start playing the video when you click on a control, and this is pretty close to JavaScript telling Firefox to start playing a video when the page loads. As a result, it makes sense that a lot of Firefox's autoplay algorithm is about figuring out if you've interacted with a page; Firefox is presumably trying to figure out if you've probably actually clicked on a 'play this video' button or the like.

The situation with bare .mp4 files surprises me a little bit, because there's no website JavaScript to obscure the situation. Firefox is presumably putting up the player controls itself, so it can know for sure whether or not you clicked on the 'play' button. Based on some quick spelunking in the Firefox source code, it appears that Firefox handles this through some chrome-level JavaScript code that calls the media's .play() method. This is the same fundamental call that website JavaScript code uses, so I suppose it's not all that surprising that it goes through the same autoplay checks; they appear to be implemented directly in the .play() handling code and apply to anything that calls it, regardless of where from or why.

This leaves me less surprised about the name and behavior of the media.autoplay.enabled preference and the other stuff involved here. Given that Firefox needs there to be some 'autoplay', clearly it could never be the case that setting media.autoplay.enabled to false disabled everything here, because then video (and probably audio) would never play. That's clearly not what people want.


Comments on this page:

So IsMediaElementAllowedToPlay() is named exactly right and does precisely what its name says… nice. I guess it’s still a bit surprising due to being placed in a file called AutoplayPolicy.cpp… but even that makes sense, albeit only with a bit of squinting.

The more I think about it based just on what you wrote, the more it makes sense for it to have to work this way. It could detect the case of a directly loaded video file by having the implicit player pass a token to play() that cannot be created from the page content, but then you have to consider frames and popups pointing directly to a video URL… so this would have to be further restricted to file: URLs. Does it have any value at that point?

Basically you’d need a way to trace the provenance of that play() call through every layer of UI abstraction. It would be theoretically doable for code under your own control I guess… but for any server- or user-supplied JS, that (momentarily surprisingly) ends up in a familiar place: damn the halting problem. 😊

s/page content/page context/

Written on 06 May 2018.
« Modern Unix GUIs now need to talk to at least one C library
One reason why Python doesn't let you overload the boolean AND and OR operations »

Page tools: View Source, View Normal, Add Comment.
Search:
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Sun May 6 00:55:53 2018
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.