Closed Bug 1755490 Opened 4 months ago Closed 3 months ago

cross-origin Iframe is not interactable behind an element with an polygon() clip-path with more than 16 vertices

Categories

(Core :: Graphics: WebRender, defect)

Firefox 97
defect

Tracking

()

RESOLVED FIXED
100 Branch
Webcompat Priority ?
Tracking Status
firefox-esr91 --- disabled
firefox97 + wontfix
firefox98 --- wontfix
firefox99 --- wontfix
firefox100 --- fixed

People

(Reporter: almog4130, Assigned: botond)

References

(Blocks 1 open bug, Regression)

Details

(Keywords: regression)

Attachments

(3 files)

Steps to reproduce:

Load an iframe, and render a div on top of that iframe
This div has clip-path property.
This issue started from the first beta version of 97.0.
This issue is only for firefox (no other widely-used browsers had this issue).
There is a simplified version of my issue here for you to see it more clearly:
https://stackoverflow.com/questions/70728597/using-clip-path-div-on-top-of-an-iframe-firefox-issue

Actual results:

The iframe isn't interactable at all, even on the places where the mask is hollowed (because of the clip-path property)

Expected results:

The iframe content should be interactable on the "missing" part of the "mask".

Blocks: fission
Status: UNCONFIRMED → NEW
Has Regression Range: --- → yes
Has STR: --- → yes
Component: Untriaged → DOM: Content Processes
Ever confirmed: true
Keywords: regression
Product: Firefox → Core
Regressed by: 1650089

Nika, this seems to be another regression from bug 1650089, but this one has better steps to reproduce. Can you check? Thanks!

Flags: needinfo?(nika)

It seems very unlikely that the regression is specifically from that bug, as the bug appears to be moreso that mouse events aren't passing through SVG masks properly when the iframe is cross-origin. I'm guessing that the regression points to that bug because without the change from that bug, one of the frames in the test case specifically happens to now be cross-process when it wasn't previously.

I'm guessing that this is a bug which has been around for all of Fission. I remember us talking about problems with mouse targeting & SVG clipping paths early during the process. Making a ni? for :hsivionen and :botond who have more context on our APZ/mouse event infrastructure and might be able to figure out what's going on here :-)

Blocks: fission-events
No longer blocks: fission
Flags: needinfo?(nika)
Flags: needinfo?(hsivonen)
Flags: needinfo?(botond)
Summary: Iframe is not interactable behind a clip-path element → cross-origin Iframe is not interactable behind a clip-path element

(In reply to Nika Layzell [:nika] (ni? for response) from comment #3)

I'm guessing that this is a bug which has been around for all of Fission. I remember us talking about problems with mouse targeting & SVG clipping paths early during the process.

That's probably bug 1675375.

I'm not sure what the right component is for this, but the issue is more around how we deal with clicking, so I don't think content processes is exactly the right component, even though maybe this is roughly a regression from Fission.

Component: DOM: Content Processes → DOM: Events
Attached file Testcase

Testcase from the StackOverflow post referenced in comment 0, packaged as a single file

Attached file Display list

It works if I use a <basic-shape> clip path, e.g. clip-path: inset(0 300px 300px 0);, instead of an SVG clip path.

That could be a workaround, if your clip path is in fact rectangular (or another kind of basic shape).

Summary: cross-origin Iframe is not interactable behind a clip-path element → cross-origin Iframe is not interactable behind an element with an SVG clip-path

As far as I can tell, the crucial hit test is in APZ in the parent process. Somehow, information about an SVG clip-path isn't making its way there.

Component: DOM: Events → Panning and Zooming
Flags: needinfo?(hsivonen)

Indeed, with Fission, since the <iframe> and its parent document live in different content processes, the decision about which one an event should target has moved from the content process to the compositor.

The compositor does its hit-testing using WebRender, and WebRender's representation of the page (the "WebRender display list") is slightly less granular than the content process's representation (the "Gecko display list"). SVG clip paths are an example of something which is not represented in the WebRender display list in a way that supports accurate hit-testing.

More specifically, WebRender supports the following kinds of clips:

  • rectangle clips
  • rounded rectangle clips
  • mask image clips, with an optional polygonal boundary

Hit testing is supported for rectangle and rounded rectangle clips, but for mask image clips, hit testing is only supported against the polygonal boundary if one has been provided; no attempt is made to hit test against the mask image itself.

In terms of the different types of clip-paths:

  • for <basic-shape> clip-paths:
    • inset produces a rectangle clip
    • circle and ellipse produce rounded rectangle clips
    • polygon produces a mask image clip, with the polygon provided as boundary
  • more complicated clip-paths such as path() and url() produce mask image clips with no polygonal boundary

So, potential improvements here could be made along one of two lines:

  1. Optimize more clip-paths into the simpler / hit-testable WebRender clips. For example, the test case in this bug has a url() clip-path pointing to a <clipPath> element with a single <rect> child -- we should be able to optimize that to a rectangle clip.
  2. Modify WebRender to support hit-testing for more complicated clip-paths. This could take the form of having WR hit-test against the mask image itself, or alternatively sending WR a different representation of the clip-path (e.g. a path) to use for hit testing.

almog4130, to help us prioritize this bug appropriately, could you provide some more information please:

  1. Are you aware of websites that are currently live that are affected by this issue?
  2. Is your use case limited to SVG clip-paths consisting of a <rect> (such that having Firefox optimize those to a rectangle clip would be sufficient), or are you also looking to use more complicated clip-paths (if so, other examples are welcome)?
  3. Does the workaround of using a <basic-shape> clip-path (and specifically inset for a rectangular clip) help you?

Thanks!

Flags: needinfo?(botond) → needinfo?(almog4130)

(In reply to Botond Ballo [:botond] from comment #12)

almog4130, to help us prioritize this bug appropriately, could you provide some more information please:

  1. Are you aware of websites that are currently live that are affected by this issue?
  2. Is your use case limited to SVG clip-paths consisting of a <rect> (such that having Firefox optimize those to a rectangle clip would be sufficient), or are you also looking to use more complicated clip-paths (if so, other examples are welcome)?
  3. Does the workaround of using a <basic-shape> clip-path (and specifically inset for a rectangular clip) help you?

Thanks!

Hi Botond,

  1. Yes, there is a link with an example of the affected product (https://codepen.io/almogadziashvili/pen/JjMEbdB)
    I have marked the polygon area with transparent blue, you can see the buttons on the header of the widget are not part of the polygon area but are not clickable on firefox 99.0b7
  2. The affected product is using clip-path: polygon(). You can see the example in (1)
  3. The affected product is using clip-path: polygon(). You can see the example in (1)

Let me know if I can help with anything else, thanks a lot!

Flags: needinfo?(almog4130)

(In reply to almog4130 from comment #13)

  1. Yes, there is a link with an example of the affected product (https://codepen.io/almogadziashvili/pen/JjMEbdB)
    I have marked the polygon area with transparent blue, you can see the buttons on the header of the widget are not part of the polygon area but are not clickable on firefox 99.0b7
  2. The affected product is using clip-path: polygon(). You can see the example in (1)
  3. The affected product is using clip-path: polygon(). You can see the example in (1)

Thanks!

As you say, this testcase uses clip-path: polygon(), which I've described in comment 11 as already being supported. However, one caveat is that there's a limit on the number of polygon vertices supported, and that limit is currently 16. The polygon in your testcase is slightly over that limit with 20 vertices.

I think we should be able to raise that limit a bit without issues.

Assignee: nobody → botond
Status: NEW → ASSIGNED

Updating bug title to reflect the revised testcase and what the patch is actually fixing.

Summary: cross-origin Iframe is not interactable behind an element with an SVG clip-path → cross-origin Iframe is not interactable behind an element with an polygon() clip-path with more than 16 vertices
Component: Panning and Zooming → Graphics: WebRender
See Also: → 1761836

(In reply to Botond Ballo [:botond] from comment #11)

So, potential improvements here could be made along one of two lines:

  1. Optimize more clip-paths into the simpler / hit-testable WebRender clips. For example, the test case in this bug has a url() clip-path pointing to a <clipPath> element with a single <rect> child -- we should be able to optimize that to a rectangle clip.

Filed bug 1761836 for this.

  1. Modify WebRender to support hit-testing for more complicated clip-paths. This could take the form of having WR hit-test against the mask image itself, or alternatively sending WR a different representation of the clip-path (e.g. a path) to use for hit testing.

It doesn't look like this is necessary for the bug reporter's use case, and based on a conversation with Jeff M. in the #gfx-firefox Matrix channel, it sounds like we would prefer not to do this for performance reasons.

There are other avenues we could explore to make such cases work, such as revisiting the decision made in bug 1541589 (relevant discussion in comments 11-14) not to implement a cross-process main thread fallback for hit testing, but we would prefer not to do that either for complexity reasons.

So, for the time being, precise hit testing for complicated clip-paths (path() and url() which cannot be optimized per bug 1761836) will continue to not be supported in the cross-process (clipped element overlays a cross-origin iframe) case. We can revisit this if compelling use cases / uses in the wild come up.

Pushed by bballo@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/1295d9c39859
Increase POLYGON_CLIP_VERTEX_MAX from 16 to 32. r=gw
Webcompat Priority: --- → ?
Status: ASSIGNED → RESOLVED
Closed: 3 months ago
Resolution: --- → FIXED
Target Milestone: --- → 100 Branch
You need to log in before you can comment on or make changes to this bug.