document-policy icon indicating copy to clipboard operation
document-policy copied to clipboard

Feature proposal: unsized-media

Open loonybear opened this issue 7 years ago • 20 comments

The proposal is to add a new feature, unsized-media, which is enabled for all origins by default (default allowlist is *)

When disabled, image or video elements (e.g. <img>, <video>, and <svg>), will be using default dimensions (300 x 150) for unspecified dimensions (width and/or height). This prevents relayout of the image or video elements.

loonybear avatar Jan 16 '18 21:01 loonybear

Please see the explainer for the proposed unsized-media policy.

jpchase avatar Apr 26 '18 00:04 jpchase

So is the goal here to change the behavior of how replaced elements are rendered or only when the replaced element is one of the elements mentioned in the document? E.g., would this affect ::before { content:url(/yolo) } or div { content:url(/yolo) }?

annevk avatar Apr 26 '18 13:04 annevk

How do you get content to jump around with <svg:image>?

annevk avatar Apr 26 '18 13:04 annevk

The high level goal is to avoid having replaced elements with an intrinsic size which gets updated after a network request completes. By declaring that image and video elements have no intrinsic size, the CSS layout algorithms default to 300x150, exactly as they would for an

content:url() should behave the same way, but I suspect it isn't covered in the proposal at all. I'm not sure if Chrome's experimental implementation handles it -- I'll have to check.

clelland avatar Apr 26 '18 13:04 clelland

The goal is specifically to be for media (image, video, svg), not all replaced elements. So, content:url isn't affected, nor are form controls. Is that strange?

It's a good question whether we need this for svg:image. I'm not familiar enough with SVG to know if it's possible to have content jumping due to an svg:image loading.

ojanvafai avatar Apr 28 '18 02:04 ojanvafai

@ojanvafai it seems a little strange architecturally, given where the sizing is done. It seems you need to plumb through the specific element names to the sizing algorithm or invoke a different algorithm at a higher-level. Having said that, perhaps the way CSS describes these things doesn't quite match implementation reality.

annevk avatar Apr 28 '18 04:04 annevk

(That's also why it's weird <svg:image> is considered, as that doesn't use replaced element sizing, as far as I know.)

annevk avatar Apr 28 '18 04:04 annevk

I'm not too familiar with implementations other than Blink and WebKit, but neither of those implements intrinsic sizing based off whether the element is replaced or not. Blink (and I believe WebKit) implement these directly in the media elements.

I think the most up to date spec on this is https://www.w3.org/TR/css-sizing-3/#intrinsic-sizes, right? @tabatkins maybe you have thoughts on what the appropriate spec language for this should be and what the <svg:image> behavior should be?

ojanvafai avatar Apr 30 '18 23:04 ojanvafai

It's currently still defined in 2.1 (all the "replaced element" sections in Chapter 10). But that section of Sizing does fill in one explicitly-undefined portion of 2.1, and has a slight behavior change the WG decided on some time ago.

I have no idea what <svg:image>’s sizing behavior is, or what compat constraints might be on it.

However, I do have opinions on how to spec this feature! We would just spec that whatever list of elements this applies to use the CSS default sizing algorithm and pretend that their intrinsic width/height/aspect-ratio is 300px/150px/2:1, rather than sizing as normal per CSS rules.

tabatkins avatar May 01 '18 18:05 tabatkins

Thanks, @tabatkins! That's the section I spent this morning looking for again.

The algorithms there, in 10.3.2 and 10.6.2, led me to believe that the spec change for this would be to declare that <img> and <video> elements would have no intrinsic size (height, width or ratio), rather than giving them the intrinsic size of the associated image (and updating that when the image becomes available)

clelland avatar May 01 '18 19:05 clelland

Sure, "no intrinsic size" also works, as far as I can tell.

tabatkins avatar May 01 '18 20:05 tabatkins

One other piece is that this should at least be compatible with future mechanisms that allow specifying what the intrinsic size or aspect-ratio of an image is. (These mechanisms would likely be created to solve the problem that there isn't a way to specify the image's intrinsic size without overriding behaviors that honor the aspect ratio. For example, it would be nice to be able to say something like <img intrinsic-width=300 intrinsic-height=480 style="width: 100%"> and have the resulting height be the one that keeps the image's aspect ratio with the 100% width, rather than the resulting height being 480px.)

In other words, this should only override sizes that would be changed by the process of the image loading and not any others... even if those others are provided by mechanisms that don't exist yet.

dbaron avatar May 01 '18 21:05 dbaron

@clelland so <img>.naturalWidth/naturalHeight/naturalRatio (if we add this one at some point) would return 0/0/0 (or null/null/null if we manage to change)?

This would also affect createImageBitmap() and such I think.

Please make sure all such observable aspects have test coverage. (Perhaps making this change by default and running a browser through web-platform-tests you find more aspects that need testing.)

annevk avatar May 02 '18 06:05 annevk

I feel like natural{Width,Height,Ratio} should still be the place where you could introspect the size of the image data, but I could be mistaken there.

I think the HTML spec could call out more clearly the distinction between the intrinsic size of the <img> element, and the intrinsic size of the image contents of that element. The natural* members of Image represent the latter, I think.

My proposal would be to declare that the element has no intrinsic size, when the feature is disabled, in the same way that the <iframe> element has no intrinsic size: even though the document contained in it has a definite size, that doesn't affect the layout of the <iframe>.

clelland avatar May 02 '18 13:05 clelland

@clelland I don't think exposing naturalWidth/naturalHeight at all works for the intended goal. Then people could still write images that are not sized, wait for it to load, read naturalWidth/Height and set it appropriately, no? So I think @annevk's suggestion or something like it is probably what we'd need to do.

@dbaron yup, that makes sense. In fact, in designing this policy, we stumbled across the need for exposing an intrinsicsize property. Proposal is here: https://github.com/ojanvafai/intrinsicsize-attribute. Feedback very welcome.

ojanvafai avatar May 05 '18 02:05 ojanvafai

(I was directed here to weigh in on the interaction with SVG's <image>; not sure if the proposal is still active or if it's waiting on better responsive aspect ratio control in markup.)

My main question: What is the actual goal of restricting this feature? Because that should influence exactly which factors are limited.

If the goal is only to prevent layout from jumping around based on content from untrusted domains, then there's no need to obfuscate the DOM properties. Also, there's no need to worry about <svg:image>, since it's size cannot affect the layout of other elements even when it is auto-sized. (In SVG 2, anyway. If we ever add automatic calculation of the <svg> element's aspect ratio based on its graphical contents, then there would be an indirect effect from an auto-sized image.)

If the goal is to prevent scripts on this domain from being able to exploit the legacy cross-origin security holes that come from being able to read an image's dimensions and confirm that it has correctly loaded, then the more extreme restrictions seem appropriate.

AmeliaBR avatar Oct 05 '18 03:10 AmeliaBR

Hi @AmeliaBR, I don't believe that this was originally intended as a security feature at all; the original intention was to stabilize layout by requiring all images to have a size that can be determined by markup / style alone. (Similar to the way that <amp-img> requires width and height to be set)

(And the proposal is still active; this is implemented in Chrome behind a flag, and there's a demo page up at https://feature-policy-demos.appspot.com/unsized-media.html)

clelland avatar Oct 05 '18 15:10 clelland

Right, this is purely a "mess me up if I write my page badly, in a way that makes the browser's job easier" feature, like the contain property. No security properties at all.

tabatkins avatar Oct 05 '18 18:10 tabatkins

Note that the current explainer is here.

It's also worth calling out that with Feature-Policy-Report-Only mode, developers could be notified of unsized media without impacting the user experience of their sites.

tdresser avatar Jan 21 '21 19:01 tdresser

Note that the current explainer is here.

It's also worth calling out that with Feature-Policy-Report-Only mode, developers could be notified of unsized media without impacting the user experience of their sites.

The explainer has been moved into this repo, at: policies/unsized-media.md.

The explainer needs to be updated to reflect the transition to Document Policy, but the link will remain the same.

jpchase avatar Jan 21 '21 22:01 jpchase