audio/video elements with autoplay attribute are inadvertently played #51

Closed
toolness opened this Issue Jan 10, 2013 · 9 comments

Comments

Projects
None yet
3 participants
@toolness

Suppose the HTML parsed by slowparse contains something like the following:

<audio src="..." autoplay>

Slowparse's default behavior is to create an actual DOM <audio> element and set its attributes accordingly. However, this actually causes the corresponding audio file to start playing, which is a side effect that the client probably doesn't intend.

Note that even if autoplay isn't enabled, the user's browser might still start buffering the media over the network in preparation for playback, which also probably isn't desired. This already happens with <img> elements too, though it's not quite as catastrophic as random audio playing from a user's browser.

@Pomax

This comment has been minimized.

Show comment Hide comment
@Pomax

Pomax Jan 23, 2013

Collaborator

We can build a browser-behaviour-less DOM by using document.createElementNS("undefined", ) for every element we encounter. The explicit, unknown namespace forces the browser to create a generic DOM node without any browser-behaviour attached to it, so things like autoplay won't trigger, and even better: media resources aren't downloaded when setting "src" or "href". Best of all, it means we don't use two different createElement functions, but can just uniformly rely on createElementNS to generate the most minimal node we need.

Collaborator

Pomax commented Jan 23, 2013

We can build a browser-behaviour-less DOM by using document.createElementNS("undefined", ) for every element we encounter. The explicit, unknown namespace forces the browser to create a generic DOM node without any browser-behaviour attached to it, so things like autoplay won't trigger, and even better: media resources aren't downloaded when setting "src" or "href". Best of all, it means we don't use two different createElement functions, but can just uniformly rely on createElementNS to generate the most minimal node we need.

@ghost ghost assigned Pomax Jan 23, 2013

@toolness

This comment has been minimized.

Show comment Hide comment
@toolness

toolness Jan 23, 2013

Nice! Would documentFragment.querySelector() still work on such a document? If not, we might want to make it a runtime option or something, so that someone who really needs that functionality (which a number of my prototypes do) can still use it.

Nice! Would documentFragment.querySelector() still work on such a document? If not, we might want to make it a runtime option or something, so that someone who really needs that functionality (which a number of my prototypes do) can still use it.

@Pomax

This comment has been minimized.

Show comment Hide comment
@Pomax

Pomax Jan 23, 2013

Collaborator

From what I can tell they're still normal DOM nodes, so querySelector still works. This will, for instance, create a "not-actually-HTMLImageElement-node" that can still be found:

var b = document.createElementNS("html","img");
b.setAttribute("src", "https://.../firefox-for-twitter.png");
b.setAttribute("id", "feirfoks");
document.body.appendChild(b);
var found = document.querySelector("#feirfoks");

But, because it's actually an anonymous node, it doesn't render as an image. However, because the namespace is "html", it (crucially) serializes as <img src=​"https:​/​/.../​firefox-for-twitter.png" id=​"feirfoks">​ rather than as an XML serialized node. Checking whether that's the case in all big browsers. If so, we have a winner!

Collaborator

Pomax commented Jan 23, 2013

From what I can tell they're still normal DOM nodes, so querySelector still works. This will, for instance, create a "not-actually-HTMLImageElement-node" that can still be found:

var b = document.createElementNS("html","img");
b.setAttribute("src", "https://.../firefox-for-twitter.png");
b.setAttribute("id", "feirfoks");
document.body.appendChild(b);
var found = document.querySelector("#feirfoks");

But, because it's actually an anonymous node, it doesn't render as an image. However, because the namespace is "html", it (crucially) serializes as <img src=​"https:​/​/.../​firefox-for-twitter.png" id=​"feirfoks">​ rather than as an XML serialized node. Checking whether that's the case in all big browsers. If so, we have a winner!

@Pomax

This comment has been minimized.

Show comment Hide comment
@Pomax

Pomax Jan 23, 2013

Collaborator

Chrome, Firefox, and Opera all work nicely. IE9 doesn't, it serializes as <img></img>...

Collaborator

Pomax commented Jan 23, 2013

Chrome, Firefox, and Opera all work nicely. IE9 doesn't, it serializes as <img></img>...

@Pomax

This comment has been minimized.

Show comment Hide comment
@Pomax

Pomax Jan 23, 2013

Collaborator

Posed http://stackoverflow.com/questions/14486547/how-does-one-make-ie9-generate-a-generic-html5-node-using-createelementns as question to world to whether we can exploit this generic node approach, or whether things will never work in IE.

Collaborator

Pomax commented Jan 23, 2013

Posed http://stackoverflow.com/questions/14486547/how-does-one-make-ie9-generate-a-generic-html5-node-using-createelementns as question to world to whether we can exploit this generic node approach, or whether things will never work in IE.

@asutherland

This comment has been minimized.

Show comment Hide comment
@asutherland

asutherland Feb 27, 2013

Member

If you create a document "loaded as data", this should stop the auto-play stuff and other similar side-effects. You would accomplish this via:
document.implementation.createHTMLDocument('')

Now, if you want to actually display that DOM tree in the page, you will need to adopt it into the tree and then stuff will start happening, etc.

See hsivonen's post on my questions about creating an HTML sanitizer for a little more info:
https://groups.google.com/d/msg/mozilla.dev.webapi/wDFM_T9v7Tc/Nr9Df4FUwuwJ

Member

asutherland commented Feb 27, 2013

If you create a document "loaded as data", this should stop the auto-play stuff and other similar side-effects. You would accomplish this via:
document.implementation.createHTMLDocument('')

Now, if you want to actually display that DOM tree in the page, you will need to adopt it into the tree and then stuff will start happening, etc.

See hsivonen's post on my questions about creating an HTML sanitizer for a little more info:
https://groups.google.com/d/msg/mozilla.dev.webapi/wDFM_T9v7Tc/Nr9Df4FUwuwJ

@Pomax

This comment has been minimized.

Show comment Hide comment
@Pomax

Pomax Mar 1, 2013

Collaborator

even better.

Collaborator

Pomax commented Mar 1, 2013

even better.

@Pomax

This comment has been minimized.

Show comment Hide comment
@Pomax

Pomax Mar 1, 2013

Collaborator

As it turns out, IE9 will still happily autoplay audio elements despite being associated with a viewport-less document. It won't do this when using document.implementation.createDocument("","html",null) but then the parsing rules are not the right ones.

Any idea how we might beat IE into submission?

Collaborator

Pomax commented Mar 1, 2013

As it turns out, IE9 will still happily autoplay audio elements despite being associated with a viewport-less document. It won't do this when using document.implementation.createDocument("","html",null) but then the parsing rules are not the right ones.

Any idea how we might beat IE into submission?

@asutherland

This comment has been minimized.

Show comment Hide comment
@asutherland

asutherland Mar 2, 2013

Member

No experience with this type of thing with IE9, sorry. I know for Gecko that some things only happen when a node/fragment actually gets appended into the document, so you could try that. The downside to that was that CSS styles did not get parsed when I did that (for gecko). Also, it looked like slowparse might already keep its fragment un-appended during my brief skim.

Member

asutherland commented Mar 2, 2013

No experience with this type of thing with IE9, sorry. I know for Gecko that some things only happen when a node/fragment actually gets appended into the document, so you could try that. The downside to that was that CSS styles did not get parsed when I did that (for gecko). Also, it looked like slowparse might already keep its fragment un-appended during my brief skim.

@Pomax Pomax closed this Nov 26, 2014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment