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

[cssom-view] Add segments property to visual viewport (#9237) #9285

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

darktears
Copy link

[cssom-view] Add segments property to visual viewport (#9237)

This property exposes in JS what is already exposed to CSS via the env() viewport segment variables. TAG review here.

Copy link
Contributor

@bokand bokand left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not an expert on segments but the text lgtm generally.

1. If the <a>visual viewport</a>'s <a for=visualviewport>associated document</a> is not <a>fully active</a>, return 0.
2. Returns null if called from within an iframe context and abort these steps.
3. Returns null if there is only a single viewport segment and abort these steps.
4. Otherwise, return the <a>visual viewport</a>'s segments array.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a definition for segments array we could link to?

Copy link
Author

@darktears darktears Sep 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what you mean but line 1861 defines what the array is. If you mean by "linking" like jumping into the spec I think I can't use <dfn attribute for=VisualViewport>segments</dfn> again without getting a warning.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see. You could link to it with but that seems rather self-referential, I was more thinking about some spec text that explains how these DOMRects are defined but I'm not sure that exists today.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could link this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That defines DOMRect interface; I mean: what values do we put to the x, y, width, height for each rect in segments? I know we say they "represent the dimensions of each existing viewport segment" but that's a bit hand wavy. i.e. what is a "viewport segment"? Is it affected by pinch-zoom? Overlay keyboards? etc.

Perhaps we could link "viewport segment" to https://drafts.csswg.org/css-env-1/#viewport-segments? I think it'd explain that this is the same thing as the env variables and if we want to make their definition more precise in the future (w.r.t my questions above) we could then do so in one place for both visualViewport.segments and the env variables.

@darktears
Copy link
Author

@bokand what do you think about the latest change?

@bokand
Copy link
Contributor

bokand commented Sep 14, 2023

lgtm!

@darktears
Copy link
Author

Feel free to merge. I'm not sure if additional reviews are required.

@bokand
Copy link
Contributor

bokand commented Sep 14, 2023

Hmm, I'm not an editor so not sure if that's ok - perhaps @smfr or @emilio could take a look?

@darktears
Copy link
Author

Yes, I think we should wait their feedback :)

@darktears
Copy link
Author

@smfr @emilio any comments?

@smfr
Copy link
Contributor

smfr commented Oct 28, 2023

I have a few thoughts, mainly about potential for user fingerprinting based on how they generally use a foldable/multi-screen device.

First, on a device that's foldable but with no hinge gap (i.e. continuous foldable screen), does the number of segments change when the screen goes between some folded state and unfolded flat? At what fold angle does this occur? If so, this might be used to identify users based on their habits of using the device fully unfolded or partially folded. This may also be used to estimate whether the user is paying full attention to the screen (fully unfolded) or is using it in a more glanceable fashion (partially folded), which may provide a signal to malicious content about when it can put things on the screen. Combined with device orientation data, this could be used to obscure activity on the less visible screen segment.

Second, there are potentially two additional means by which screen segment data could leak per-user fingerprintable data. If an OS allows the user to position a window freely in a way that spans screens, the segments API is way to leak the window position (the segment geometry would change based on window position). This is akin to desktop browsers exposing window.screenX/screenY which can be very user-specific. In addition, even with non-draggable windows but modifiable browser UI including toolbars, the segments would leak information about the UI/toolbar geometry.

@darktears
Copy link
Author

darktears commented Oct 30, 2023

The number of segments changes when the screen goes between the folded state and unfolded flat indeed. That's the essence of the API in the first place which is the same goal than the CSS MQs added in MQ Level 5. Here we're just basically providing the same functionality to JavaScript developers where CSS isn't a good fit (e.g. Canvas based content).

I think we need to take a step back here. User is expected to pay full attention when the device is in a folded state. The entire idea of the form factor is to provide bigger screen estate for content when the device is half folded and the keyboard detached. Even on smaller foldable form factors like smartphones typically content author will display a split ux. Have a look here to see various pictures of devices in action. There is also plenty of pictures online showcasing the Samsung foldables with their split UX ideas.

Regarding the potential fingerprinting, on Chromium browser segments are only returned when the browser window is in fullscreen or maximized, this is an implementation choice which we can decide to standardize or not. We did not hear from content authors the need to get segments when the window isn't maximized and floating around. As a clarification the browser window is not resized when changing state (e.g. folded to unfolded) but could be if the keyboard is docked for example.

I want to emphasize that the segments are defined in client coordinates (so adjusted to zoom factor and so forth) therefore relative to the viewport. I'm not sure how much information they would "leak" provided that say top segment + bottom segment will be equivalent to the inner height/width of the viewport.

Could you use these APIs to fingerprint that it's a folded device? Yes sure but again today you can do that by checking the window dimensions because they have not so common sizes (including for example Android where the dimensions are off for a tablet and a typical phone). Can you use these APIs to fingerprint a specific foldable model? Likely no because many of them share the same panel dimensions/sizes (phone or not) but again even if one had an exotic panel, they add nothing more than what I could already derive from the viewport size.

Thanks for your comments. I'll be happy to clarify more if you need so.

@@ -1806,6 +1806,8 @@ interface VisualViewport : EventTarget {

readonly attribute double scale;

readonly attribute FrozenArray&lt;DOMRect> segments;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you need the &lt;?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think a FrozenArray can be used tho, right? A FrozenArray is supposed to be immutable (https://webidl.spec.whatwg.org/#idl-frozen-array), but this is mutable right?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should just be a sequence?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you need the &lt;?

I get an error otherwise.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think a FrozenArray can be used tho, right? A FrozenArray is supposed to be immutable (https://webidl.spec.whatwg.org/#idl-frozen-array), but this is mutable right?

It's frozen because it's not changing, just like any other property of visualviewport. You're expected to listen for some events to query the new state (e.g. resize). If just the posture is changed then Device Posture API has an event listener specifically for that. Both APIs are complimentary.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's frozen because it's not changing, just like any other property of visualviewport. You're expected to listen for some events to query the new state (e.g. resize). If just the posture is changed then Device Posture API has an event listener specifically for that. Both APIs are complimentary.

Well but that means that they do change (when the event fires) right? or what am I missing?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is a concrete example: initial page load and the device is used flat (or a laptop posture with the keyboard docked) the segments property will be 0 meaning an array of 0 length.

If I change the posture to folded (or detach the keyboard) then the events will fire and the segments property will have an array of 2 segments representing the two sides beside the fold/hinge.

Just like the other properties of the visual viewport segments they represent the given state at the time window.visualViewport was queried.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I get that, the point is that my understanding is that FrozenArrays aren't supposed to change, ever, not even in reactions to an event. @domenic is that right?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FrozenArray properties can change. The contents of the array cannot, but a new array can start being returned.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that it is invalid for attributes to be sequences; that is part of why FrozenArray exists.


Note: Based on the data returned for each viewport segment, developers will be able to infer the number of hinges available as well as the hinge orientation.
The browser window can be moved/resized such that the number of segments and/or their dimensions change.
In these cases, resize events will fire at which point authors should re-query this property, as the returned FrozenArray is just a snapshot of the current state.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be good to note here that these are returned in un-zoomed CSS pixels. It's a bit weird that these are part of the VisualViewport API even though they don't have anything to do with it right? In particular, they don't change when zooming and panning, right?

Or do those environment variables change when zooming and panning? That seems unfortunate if so.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They don't change when zooming or panning. But unless I don't understand your point, I'm not sure why they have "anything to do" with the viewport? For example, on a symmetrical folding device which is in a folded state, they're helping developers to implement say a split UX/dual pane view in their app/websites which is basically dividing the viewport in half logically and they need the segments to do so. But again, maybe I misinterpreted your comment.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@emilio : Take a look here. You can see in the pictures what the API is trying to achieve in JS, similar to what the CSS API is doing.

Copy link
Collaborator

@fantasai fantasai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding new features (or substantially changing existing ones) requires CSSWG approval, not just editor approval... it doesn't seem like #9237 has that?

@fantasai fantasai marked this pull request as draft November 20, 2023 22:02
@darktears
Copy link
Author

Adding new features (or substantially changing existing ones) requires CSSWG approval, not just editor approval... it doesn't seem like #9237 has that?

I believe it doesn't have approval (at least I didn't request but I'm not sure what MSFT did in the past). The CSS equivalent (MQs) is already in https://drafts.csswg.org/css-env-1/#viewport-segments and MQ Level 5 (https://www.w3.org/TR/mediaqueries-5/#mf-horizontal-viewport-segments). It's essentially the exact same feature, just at a JS level. Anyway, how do I request such approval?

@aykutbulut
Copy link

Privacy section in the explainer indicates that segments will return null when called from within an iframe and explains how this prevents using the API as a fingerprinting vector from cross origin iframes.

A concern I have is accessing the segments through CSS media queries. Having CSS API in iframes might enable this type of fingerprinting. Is disabling CSS media queries for the segments feasible?

@darktears
Copy link
Author

darktears commented Mar 27, 2024

Privacy section in the explainer indicates that segments will return null when called from within an iframe and explains how this prevents using the API as a fingerprinting vector from cross origin iframes.

A concern I have is accessing the segments through CSS media queries. Having CSS API in iframes might enable this type of fingerprinting. Is disabling CSS media queries for the segments feasible?

Do we have precedence in doing that? I couldn't find anything in CSS specifications where certain CSS features are restricted to iframes, especially in the MQ/CSS env context but the domain is vast so I could have been missing something.

But again, the real question is whether the fingerprinting is really that big of an issue if segments are just subdivisions of the total viewport size. Foldables already have exotic viewport size when unfolded so they can be identified already but as more devices are in the market, targeting a specific device is becoming harder as they share panel dimensions so segments definition as well.

You could use this to detect how the device is being used (folded vs not) but the Device Posture API already reveal that. One could argue that in some way it is like the pointer MQ which is dynamic and exposing whether a device with detachable keyboard has it connected or not, also revealing how the device is being used.

Yes, it does add a bit of entropy but nothing that couldn't be derived from the viewport size today (or even combining with other APIs) but I'm open to discussing this further.

@aykutbulut
Copy link

I am not aware of such a precedence. I agree with your arguments.

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

Successfully merging this pull request may close these issues.

None yet

7 participants