Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature proposal: unsized-media #1

Open
loonybear opened this issue Jan 16, 2018 · 20 comments
Open

Feature proposal: unsized-media #1

loonybear opened this issue Jan 16, 2018 · 20 comments

Comments

@loonybear
Copy link

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.

@jpchase
Copy link
Contributor

jpchase commented Apr 26, 2018

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

@annevk
Copy link

annevk commented Apr 26, 2018

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
Copy link

annevk commented Apr 26, 2018

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

@clelland
Copy link
Collaborator

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 <iframe>, unless some other constraint forces it to the correct size.

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.

@ojanvafai
Copy link
Member

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.

@annevk
Copy link

annevk commented Apr 28, 2018

@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
Copy link

annevk commented Apr 28, 2018

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

@ojanvafai
Copy link
Member

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?

@tabatkins
Copy link

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.

@clelland
Copy link
Collaborator

clelland commented May 1, 2018

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)

@tabatkins
Copy link

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

@dbaron
Copy link

dbaron commented May 1, 2018

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.

@annevk
Copy link

annevk commented May 2, 2018

@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.)

@clelland
Copy link
Collaborator

clelland commented May 2, 2018

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>.

@ojanvafai
Copy link
Member

@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.

@AmeliaBR
Copy link

AmeliaBR commented Oct 5, 2018

(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.

@clelland
Copy link
Collaborator

clelland commented Oct 5, 2018

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)

@tabatkins
Copy link

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.

@clelland clelland transferred this issue from w3c/webappsec-permissions-policy Dec 1, 2020
@tdresser
Copy link

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.

@jpchase
Copy link
Contributor

jpchase commented Jan 21, 2021

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants