-
Notifications
You must be signed in to change notification settings - Fork 522
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
Proposal for V2: occlusion detection #295
Comments
In terms of efficient implementation, we at Chrome Rendering think it should be relatively straightforward Here is some pseudocode:
A rect-based HitTest and RootViewportVisualRect are already implemented in Chrome, and should hopefully already be present in other browsers as well. Edge even has a rect-based In Chrome, the rect-based hit testing is already needed for gesture disambiguation on Android, for example. RootViewportVisualRect is used for raster invalidation. |
Bikeshedding: s/isVisible/isGuaranteedVisible/ to make it more clear what it's actually measuring. |
So I don't think Gecko has rect-based hit-testing code, so we'd need to implement it in order to implement this feature. That makes it seem like a pretty substantial feature from our end. (What other web features does your rect-based hit testing support?) It would be interesting to hear about the use cases for this. Is this something that sites (ads?) are widely simulating today using JS APIs, in ways that perform poorly? Or is it rarely simulated but more requested, or just requested? Some of the use cases seem to be about checking visibility for various security use cases. If that's a use case, then it creates a new class of security vulnerability: false positive reports in this API. How confident are you that that space is easy to secure? It seems like there are a lot of web features that can occlude or clip things. |
We use rect-based hit testing to figure out the target of touch events. It's not necessary to implement rect-based hit testing, but it's a convenient path to implementation if it's present. My original implementation idea -- and we may yet return to it -- is to first walk the graphics layers and look for overlap with graphics layers that paint on top of the target element; and then to walk the list of painted objects in the target graphics layer, starting from the target element, and check for overlaps. The primary motivation is to eliminate common patterns of fraud and abuse on the web, and to enable trust relationships between embedded third-party iframes and their host documents. Specifically, it gives the iframe a strong guarantee that its content is visible on screen, and has not been painted over or altered in any way by the embedding document. Some of the likely use cases are shown in the slide deck, including:
Given the motivation, the idea is that a conforming implementation may sometimes give false negatives (i.e., report a target as "possible occluded" when it's actually visible), but must never give a false positive (i.e., report a target as "definitely visbile" when it's actually occluded). We're pretty sure that's achievable in chromium, but I don't know enough about other browser implementations to know how difficult it would be for them. |
I would also add that, to my knowledge, there is no existing functionality that comes close to what V2 would offer. This is in contrast to V1, which mostly offers information that can be had by other means. I believe V2 would be an entirely novel capability. |
We have spoken with engineers who work on ad tracking systems. It is clear that all large ad tracking For these reasons, even with IOv1, ad trackers still need to run a setTimeout polling operation in order to try to detect occlusion. And in the setTimeout callback they run a lot of expensive code. One example we have seen is that they use the elementFromPoint API at the center point of an ad to simulate a hit test. (This is both expensive and also inaccurate because it can't cross non-same-origin Ad tracking systems which perform such a hit test will of course only get faster if they use the |
I can confirm with absolute confidence that the clickjacking problem is a mess, there's no existing way to solve it, and people are deploying terrible code all the time in an attempt to try. I ended up getting pretty involved in the subject, building an early PoC to show something could be done graphically to address the issue (code at https://github.com/dakami/ironframe , slides at https://dankaminsky.com/2015/08/09/defcon-23-lets-end-clickjacking/ ). This is very cool. |
For others following this issue: the spec is currently at http://w3c.github.io/IntersectionObserver/v2/ |
The V2 spec proposal shipped in chromium earlier this year: |
AFAIK there still isn't a spec for hit testing (see https://w3c.github.io/csswg-drafts/css-ui/#issue-bdab65a4), although https://w3c.github.io/csswg-drafts/cssom-view/#dom-document-elementsfrompoint exists which depends on hit testing and is implemented across the board https://caniuse.com/mdn-api_document_elementsfrompoint |
Hmm however |
You are right that there is no definition of hit testing yet in a specification. Likewise, there is not yet a precise definition in a spec of ink overflow (see w3c/csswg-drafts#8649). Previous discussions of IntersectionObserver occlusion testing have blocked on this problem, because making it precisely defined impacts interoperability. If we can agree on the usefulness of occlusion detection and the definition in the "v2" IntersectionObserver spec, then we can go and define hit testing and visual overflow elsewhere as needed in order to support specifying occlusion.
Yes. However, even before this feature, Chromium already needed to do rect-based hit testing for the purpose of mobile hit testing, where user touches are not precise enough to use a single point. The definition of the rect-based hit test is a simple generalization of a point-based hit test. |
Note that the proposed spec doesn't mention hit testing; it says: "If the implementation cannot guarantee that the target is completely unoccluded by other page content, [set isVisible to] false." We found it convenient to use the existing hit testing code, with some modifications, to implement this functionality in chromium. But occlusion detection requires somewhat different behavior from the hit-testing used for elementsFromPoint and event targeting, so even if there were a spec for hit testing, it would need exceptions. |
The WG held a meeting to discuss this issue this week. Outcomes:
Notes
Stefan: Designed this feature and talked to a lot of people about security concerns and use cases. Have some strong evidence from Google partners that it works well for security purposes. Used on about 5% of page loads in Chrome. Feedback received from Google-internal teams is quite positive about the feature in practice.
Stefan: one use case is a sign-in widget in an iframe on an untrusted site, without having a popup window or other types of interstitial.
Emilio: is the use case to guarantee that nothing at all is on top of the element?
Stefan: nothing painted on top at all, including blurs and non-zero opacity. Does not block a malicious site from taking events, but they can’t draw on top.
Stefan: there are some cases where the iframe is actually visible but for some reasons the site uses an innocuous type of rounded corner etc.
Stefan: spec is biased towards guaranteeing no false positives (i.e. “reported visible but is actually occluded”). There are some corner case implementation-dependent things where browser interop might not happen at present, such as precisely defining blur radius of a box shadow.
Chris: is blur radius or filter radius the only non-interoperable issue?
Stefan: drop shadows also.
Chris: if those are the only cases, then I think it’s doable to specify exactly.
Emilio: choice of fonts can vary by OS or browser, so the outcome may be different on the same page for different browsers.
Chris: if sites really want to get the same output, they can use a web font / override ascents & descents.
Emilio: have not heard demand for this feature outside of Google teams. Probably not opposed to implementing this, but is there more demand from elsewhere?
Stefan: occlusion testing is a genuinely novel feature that cannot be computed in any other ways (as opposed to v1, which is polyfillable)
Stefan: hit testing is expensive compared with other parts of IO, and so it’s performance-positive to avoid work through integration with that feature.
Chris: we’ve also been able to tune the implementation over time to throttle cases where IO was using up too much CPU time in the aggregate.
Chris: Emilio and Simon, does all this sound compelling?
Emilio: would be good to demonstrate more developer demand for it.
Stefan: have heard from external developers who want the feature, will pass along the feedback.
Stefan: there is a “delay” feature for how often measurements happen, and if occlusion testing is on we ignore values less than 100ms. Think it would be good to add the delay feature independent of occlusion testing, since that allows developers to tune their own performance.
Emilio: what about cases where delay causes a persistent error state due to delay?
Chris: let’s split out delay into its own separate feature request from occlusion testing.
|
Updates... This feature is currently being used on ~6% of page loads in Chrome, and by ~8% of top websites, which is I think a pretty strong indicator of web developer interest, especially considering the feature is only available in chromium-based browsers. It was proposed as an Interop 2024 goal (but not adopted). The biggest implementation concern raised at prior meetings was the challenge of making this feature interoperable without a detailed specification of ink overflow. Hoping to make headway on that issue... |
I've attempted to address the interop concerns with a few PR's that specify the extent of ink overflow: w3c/csswg-drafts#9823 The first two PR's have been merged. There is currently discussion on csswg-drafts#8649 about whether the last two should be accepted; we hope to get resolution at next week's CSSWG meeting. I'd like to ask for feedback from the participants on this issue as to whether those PR's adequately allay the interop concerns around relying on ink overflow to determine occlusion. I've created a PR that adds the V2 feature set to the spec, and I'd like to move forward with it if there is agreement. |
Members of the WebApps WG met on May 9 to discuss this proposal. No significant objections were raised, and @emilio agreed to review the spec PR and work towards getting a formal standards position from Mozilla. A few specific topics that were discussed:
|
[IntersectionObserver] #295 V2: visibility detection
I propose that the IntersectionObserver spec be extended to allow for detection of occlusion by other content.
Here's an early draft of the proposed spec change:
http://szager-chromium.github.io/IntersectionObserver/
Special attention should be paid to this section, which describes the heuristics for occlusion detection:
http://szager-chromium.github.io/IntersectionObserver/#calculate-visibility-algo
The intention with that language is to make it possible to implement the feature efficiently; and to make it maximally useful for the anticipated primary use cases. Here's a small slide deck explaining the motivation and anticipated use cases for this feature:
https://docs.google.com/presentation/d/13-M2eqNKnClEPXiEQK2iwvnk3njqssj4OzDuZCSe_jQ/edit?usp=sharing
The text was updated successfully, but these errors were encountered: