Search in page can't find text in offscreen overflow:hidden containers
Categories
(Core :: Find Backend, defect, P2)
Tracking
()
Tracking | Status | |
---|---|---|
firefox77 | --- | fixed |
People
(Reporter: florian, Assigned: emilio)
References
(Regressed 1 open bug)
Details
Attachments
(6 files, 5 obsolete files)
Reporter | ||
Comment 1•6 years ago
|
||
Reporter | ||
Comment 2•6 years ago
|
||
Reporter | ||
Comment 3•6 years ago
|
||
Comment 4•6 years ago
|
||
Comment 5•6 years ago
|
||
Updated•6 years ago
|
Updated•6 years ago
|
Comment 8•6 years ago
•
|
||
This has a strange, interesting cause. At https://searchfox.org/mozilla-central/rev/2a6f3dde00801374d3b2a704232de54a132af389/layout/base/PresShell.cpp#3586, we are checking for the directional visibility of a target rect relative to the intersection of the rects of all of its scroll frame ancestors, including the root scroll frame. Either the rect should be partly visible, or should be scrollable into view either up, down, left, or right. Here's what's happening in this case:
- Text frames are enclosed in an overflow:hidden element, which creates a scroll frame.
- The text of interest is off the bottom of the visible area. That means the correct result would be to return nsRectVisibility_kBelowViewport.
- This algorithm intersects the off-screen scroll frame with the root scroll frame and comes up with an empty rect LOCATED AT THE ORIGIN of the off-screen scroll frame. This is because of how we define our Intersect function at https://searchfox.org/mozilla-central/rev/2a6f3dde00801374d3b2a704232de54a132af389/gfx/2d/BaseRect.h#112.
- The algorithm then deflates the empty visible area rect, which pushes it slightly right and down. It is still empty, but now its origin is inside the bounds of the text frame.
- The algorithm concludes that since the text frame is neither wholly above, below, to the left or right of the (empty) visible rect, it must be visible.
I'm not sure what the best solution will be, though one option may be to post-process an empty visible rect after Step 3 to favor a different origin.
Updated•6 years ago
|
Comment 9•6 years ago
|
||
Comment 10•6 years ago
|
||
attachment 9049392 [details] solves the original issue, but reveals another issue that I'd like to characterize better before closing this bug. With a similar local testcase, the text is always found, but not always scrolled into view. It appears to be related to some transform that is not accounted for when determining if a range is visible.
I've attached my local testcase here. You may be able to reproduce this new issue by applying the attachment 9049392 [details] patch and then searching repeatedly for "task2". The text will consistently be found, but not always scrolled into view.
Comment 11•6 years ago
|
||
This attachment is a minimal testcase. Searching for the test "findme" fails to scroll the text into view. Here's the reason:
nsIPresShell::ScrollFrameRectIntoView() walks up from the found nsTextFrame and attempts to scroll it into view. It does this by walking up the frame ancestor chain. For each scrollframe ancestor, it scrolls it if necessary and possible. For EVERY ancestor frame, it transforms the nsTextFrame rect into the ancestor's coordinate space.
In this case:
- The first scrollFrame ancestor has overflow-y:scroll, so could scroll if it wanted to. However, it decides that the nsTextFrame is within its scrollportrect, so it doesn't attempt to scroll.
- The body is the next scrollFrame ancestor, and it has overflow:hidden, so it can't scroll to the nsTextFrame.
So a possible fix will be to make each scrollportrect intersect with the top level scrollportrect for purposes of determining the need to scroll into view. Something like that.
Comment 12•6 years ago
|
||
In addition to the existing callsite, this new function will be useful
for other functions that want to compare against the scroll ancestor
visible area.
Depends on D22626
Comment 13•6 years ago
|
||
This patch propagates the top level visible area through to all the calls
to ScrollToShowRect() for purposes of intersection with the local
scrollFrame's visible area.
Depends on D23420
Comment 14•6 years ago
|
||
This test has a scrollable div within a non-scrollable div. The scrollable
div has a size big enough to include the target text, but it's clipped
by the non-scrollable div. The other changes in this patch ensure that
the scrollable div only considers its visible area intersected with
the viewport visible area, ensuring that the text is not only found,
but scrolled into view.
Depends on D23422
Comment 15•6 years ago
|
||
Comment 17•6 years ago
|
||
Sorry for the long delay in reviews. I'm going to start reviewing these patches today.
Comment 18•6 years ago
|
||
(In reply to Markus Stange [:mstange] from comment #17)
Sorry for the long delay in reviews. I'm going to start reviewing these patches today.
There are still test failures I haven't resolved. I would still like your review on what's posted, because if you spot any questionable choices there, it might help me spot the changes needed. If you don't want to be in that position, feel free to resign as reviewer and I'll re-apply you when the patches are solid.
Assignee | ||
Comment 19•5 years ago
|
||
Any update on this Brad? Any way I can help?
Comment 20•5 years ago
|
||
(In reply to Emilio Cobos Álvarez (:emilio) from comment #19)
Any update on this Brad? Any way I can help?
Ack, it's been so long. I'll rebase the patches and send a new try server push to see the state of the tests.
Updated•5 years ago
|
Comment 21•5 years ago
|
||
Comment 22•5 years ago
|
||
This is necessary because the test is designed to scroll a frame into
view within its container's viewport. The test currently does this
within a window that is too small to show all the viewports being
tested. Changes in this patch series makes the root viewport also
be considered for whether or not a frame has been scrolled into view.
Depends on D23428
Comment 24•5 years ago
|
||
Comment 25•5 years ago
|
||
Comment 26•5 years ago
|
||
Comment 28•5 years ago
|
||
Any updates on this issue?
Assignee | ||
Updated•5 years ago
|
Comment 29•5 years ago
|
||
It's currently waiting on my review. I really hope to get to it soon.
Assignee | ||
Comment 31•5 years ago
|
||
Multiple issues here. The IsRangeVisible code was wrong, it was returning false
for ranges that were perfectly valid, but outside the viewport, because the
following piece of code:
if (!aMustBeInViewPort) {
// This is an early exit case because we don't care that that range
// is out of viewport, so we return that the range is "visible".
return true;
}
Was incorrectly after some stuff checking viewport visibility. This code is
pretty complex for no good reason, it wants to do something very
simple: Start from the visible selection if possible.
This patch still achieves this, using IsRangeRendered (which does a proper
hit-test to figure out if a range is in the viewport). Should have no behavior
differences except for non-collapsed ranges that are partially inside the
viewport.
Updated•5 years ago
|
Updated•5 years ago
|
Updated•5 years ago
|
Updated•5 years ago
|
Updated•5 years ago
|
Assignee | ||
Comment 32•5 years ago
|
||
Comment 33•5 years ago
|
||
Comment 34•5 years ago
|
||
Backed out for geckoview assertion error
backout: https://hg.mozilla.org/integration/autoland/rev/5c4dea9c2760d76b00abdea5ff74df04e2c604d2
failure log: https://treeherder.mozilla.org/logviewer.html#/jobs?job_id=297866186&repo=autoland&lineNumber=3267
[task 2020-04-16T03:01:36.631Z] 03:01:36 INFO - TEST-START | org.mozilla.geckoview.test.FinderTest.find
[task 2020-04-16T03:01:37.584Z] 03:01:37 INFO - org.mozilla.geckoview.test | INSTRUMENTATION_STATUS: numtests=674
[task 2020-04-16T03:01:37.585Z] 03:01:37 INFO - org.mozilla.geckoview.test | INSTRUMENTATION_STATUS: stream=
[task 2020-04-16T03:01:37.586Z] 03:01:37 INFO - org.mozilla.geckoview.test | Error in find(org.mozilla.geckoview.test.FinderTest):
[task 2020-04-16T03:01:37.587Z] 03:01:37 INFO - org.mozilla.geckoview.test | java.lang.AssertionError: Should have wrapped
[task 2020-04-16T03:01:37.589Z] 03:01:37 INFO - org.mozilla.geckoview.test | Expected: <true>
[task 2020-04-16T03:01:37.590Z] 03:01:37 INFO - org.mozilla.geckoview.test | but: was <false>
[task 2020-04-16T03:01:37.592Z] 03:01:37 INFO - org.mozilla.geckoview.test | at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
[task 2020-04-16T03:01:37.594Z] 03:01:37 INFO - org.mozilla.geckoview.test | at org.junit.Assert.assertThat(Assert.java:956)
[task 2020-04-16T03:01:37.597Z] 03:01:37 INFO - org.mozilla.geckoview.test | at org.junit.rules.ErrorCollector$1.call(ErrorCollector.java:65)
[task 2020-04-16T03:01:37.599Z] 03:01:37 INFO - org.mozilla.geckoview.test | at org.junit.rules.ErrorCollector.checkSucceeds(ErrorCollector.java:78)
[task 2020-04-16T03:01:37.603Z] 03:01:37 INFO - org.mozilla.geckoview.test | at org.junit.rules.ErrorCollector.checkThat(ErrorCollector.java:63)
[task 2020-04-16T03:01:37.605Z] 03:01:37 INFO - org.mozilla.geckoview.test | at org.mozilla.geckoview.test.rule.GeckoSessionTestRule.checkThat(GeckoSessionTestRule.java:801)
[task 2020-04-16T03:01:37.605Z] 03:01:37 INFO - org.mozilla.geckoview.test | at org.mozilla.geckoview.test.BaseSessionTest.assertThat(BaseSessionTest.kt:81)
[task 2020-04-16T03:01:37.605Z] 03:01:37 INFO - org.mozilla.geckoview.test | at org.mozilla.geckoview.test.FinderTest.find(FinderTest.kt:28)
[task 2020-04-16T03:01:37.605Z] 03:01:37 INFO - org.mozilla.geckoview.test | at java.lang.reflect.Method.invoke(Native Method)
[task 2020-04-16T03:01:37.605Z] 03:01:37 INFO - org.mozilla.geckoview.test | at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
[task 2020-04-16T03:01:37.606Z] 03:01:37 INFO - org.mozilla.geckoview.test | at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
[task 2020-04-16T03:01:37.606Z] 03:01:37 INFO - org.mozilla.geckoview.test | at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
[task 2020-04-16T03:01:37.606Z] 03:01:37 INFO - org.mozilla.geckoview.test | at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
[task 2020-04-16T03:01:37.606Z] 03:01:37 INFO - org.mozilla.geckoview.test | at org.mozilla.geckoview.test.rule.GeckoSessionTestRule$2.lambda$evaluate$0$GeckoSessionTestRule$2(GeckoSessionTestRule.java:1284)
[task 2020-04-16T03:01:37.606Z] 03:01:37 INFO - org.mozilla.geckoview.test | at org.mozilla.geckoview.test.rule.-$$Lambda$GeckoSessionTestRule$2$sIbRNaZJgAu-QrUVWSGD8JbPSWM.run(lambda)
[task 2020-04-16T03:01:37.606Z] 03:01:37 INFO - org.mozilla.geckoview.test | at android.app.Instrumentation$SyncRunnable.run(Instrumentation.java:1950)
[task 2020-04-16T03:01:37.607Z] 03:01:37 INFO - org.mozilla.geckoview.test | at android.os.Handler.handleCallback(Handler.java:751)
[task 2020-04-16T03:01:37.608Z] 03:01:37 INFO - org.mozilla.geckoview.test | at android.os.Handler.dispatchMessage(Handler.java:95)
[task 2020-04-16T03:01:37.609Z] 03:01:37 INFO - org.mozilla.geckoview.test | at android.os.Looper.loop(Looper.java:154)
[task 2020-04-16T03:01:37.609Z] 03:01:37 INFO - org.mozilla.geckoview.test | at android.app.ActivityThread.main(ActivityThread.java:6077)
[task 2020-04-16T03:01:37.610Z] 03:01:37 INFO - org.mozilla.geckoview.test | at java.lang.reflect.Method.invoke(Native Method)
[task 2020-04-16T03:01:37.610Z] 03:01:37 INFO - org.mozilla.geckoview.test | at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
[task 2020-04-16T03:01:37.611Z] 03:01:37 INFO - org.mozilla.geckoview.test | at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
[task 2020-04-16T03:01:37.612Z] 03:01:37 INFO - org.mozilla.geckoview.test |
[task 2020-04-16T03:01:37.612Z] 03:01:37 INFO - org.mozilla.geckoview.test | INSTRUMENTATION_STATUS: id=AndroidJUnitRunner
[task 2020-04-16T03:01:37.613Z] 03:01:37 INFO - org.mozilla.geckoview.test | INSTRUMENTATION_STATUS: test=find
[task 2020-04-16T03:01:37.613Z] 03:01:37 INFO - org.mozilla.geckoview.test | INSTRUMENTATION_STATUS: class=org.mozilla.geckoview.test.FinderTest
[task 2020-04-16T03:01:37.613Z] 03:01:37 INFO - org.mozilla.geckoview.test | INSTRUMENTATION_STATUS: stack=java.lang.AssertionError: Should have wrapped
[task 2020-04-16T03:01:37.614Z] 03:01:37 INFO - org.mozilla.geckoview.test | Expected: <true>
[task 2020-04-16T03:01:37.614Z] 03:01:37 INFO - org.mozilla.geckoview.test | but: was <false>
[task 2020-04-16T03:01:37.615Z] 03:01:37 INFO - org.mozilla.geckoview.test | at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
[task 2020-04-16T03:01:37.615Z] 03:01:37 INFO - org.mozilla.geckoview.test | at org.junit.Assert.assertThat(Assert.java:956)
[task 2020-04-16T03:01:37.616Z] 03:01:37 INFO - org.mozilla.geckoview.test | at org.junit.rules.ErrorCollector$1.call(ErrorCollector.java:65)
[task 2020-04-16T03:01:37.616Z] 03:01:37 INFO - org.mozilla.geckoview.test | at org.junit.rules.ErrorCollector.checkSucceeds(ErrorCollector.java:78)
[task 2020-04-16T03:01:37.617Z] 03:01:37 INFO - org.mozilla.geckoview.test | at org.junit.rules.ErrorCollector.checkThat(ErrorCollector.java:63)
[task 2020-04-16T03:01:37.617Z] 03:01:37 INFO - org.mozilla.geckoview.test | at org.mozilla.geckoview.test.rule.GeckoSessionTestRule.checkThat(GeckoSessionTestRule.java:801)
[task 2020-04-16T03:01:37.618Z] 03:01:37 INFO - org.mozilla.geckoview.test | at org.mozilla.geckoview.test.BaseSessionTest.assertThat(BaseSessionTest.kt:81)
[task 2020-04-16T03:01:37.618Z] 03:01:37 INFO - org.mozilla.geckoview.test | at org.mozilla.geckoview.test.FinderTest.find(FinderTest.kt:28)
[task 2020-04-16T03:01:37.619Z] 03:01:37 INFO - org.mozilla.geckoview.test | at java.lang.reflect.Method.invoke(Native Method)
[task 2020-04-16T03:01:37.619Z] 03:01:37 INFO - org.mozilla.geckoview.test | at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
[task 2020-04-16T03:01:37.620Z] 03:01:37 INFO - org.mozilla.geckoview.test | at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
[task 2020-04-16T03:01:37.620Z] 03:01:37 INFO - org.mozilla.geckoview.test | at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
[task 2020-04-16T03:01:37.621Z] 03:01:37 INFO - org.mozilla.geckoview.test | at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
[task 2020-04-16T03:01:37.621Z] 03:01:37 INFO - org.mozilla.geckoview.test | at org.mozilla.geckoview.test.rule.GeckoSessionTestRule$2.lambda$evaluate$0$GeckoSessionTestRule$2(GeckoSessionTestRule.java:1284)
[task 2020-04-16T03:01:37.622Z] 03:01:37 INFO - org.mozilla.geckoview.test | at org.mozilla.geckoview.test.rule.-$$Lambda$GeckoSessionTestRule$2$sIbRNaZJgAu-QrUVWSGD8JbPSWM.run(lambda)
[task 2020-04-16T03:01:37.623Z] 03:01:37 INFO - org.mozilla.geckoview.test | at android.app.Instrumentation$SyncRunnable.run(Instrumentation.java:1950)
[task 2020-04-16T03:01:37.623Z] 03:01:37 INFO - org.mozilla.geckoview.test | at android.os.Handler.handleCallback(Handler.java:751)
[task 2020-04-16T03:01:37.623Z] 03:01:37 INFO - org.mozilla.geckoview.test | at android.os.Handler.dispatchMessage(Handler.java:95)
[task 2020-04-16T03:01:37.624Z] 03:01:37 INFO - org.mozilla.geckoview.test | at android.os.Looper.loop(Looper.java:154)
[task 2020-04-16T03:01:37.624Z] 03:01:37 INFO - org.mozilla.geckoview.test | at android.app.ActivityThread.main(ActivityThread.java:6077)
[task 2020-04-16T03:01:37.625Z] 03:01:37 INFO - org.mozilla.geckoview.test | at java.lang.reflect.Method.invoke(Native Method)
[task 2020-04-16T03:01:37.626Z] 03:01:37 INFO - org.mozilla.geckoview.test | at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
[task 2020-04-16T03:01:37.626Z] 03:01:37 INFO - org.mozilla.geckoview.test | at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
[task 2020-04-16T03:01:37.627Z] 03:01:37 INFO - org.mozilla.geckoview.test |
[task 2020-04-16T03:01:37.627Z] 03:01:37 INFO - org.mozilla.geckoview.test | INSTRUMENTATION_STATUS: current=110
[task 2020-04-16T03:01:37.628Z] 03:01:37 INFO - org.mozilla.geckoview.test | INSTRUMENTATION_STATUS_CODE: -2
[task 2020-04-16T03:01:37.628Z] 03:01:37 WARNING - TEST-UNEXPECTED-FAIL | org.mozilla.geckoview.test.FinderTest.find | java.lang.AssertionError: Should have wrapped
[task 2020-04-16T03:01:37.628Z] 03:01:37 INFO - TEST-INFO took 973ms
Assignee | ||
Updated•5 years ago
|
Assignee | ||
Comment 35•5 years ago
|
||
It makes no sense that the first thing in the session would be considered as
wrapping, it was happening only because we were incorrectly failing to find a
"visible" range deep in Gecko (so we started back from the beginning of the
document, wrapping).
Assignee | ||
Updated•5 years ago
|
Comment 36•5 years ago
|
||
Comment 37•5 years ago
|
||
bugherder |
https://hg.mozilla.org/mozilla-central/rev/ff7529683179
https://hg.mozilla.org/mozilla-central/rev/cf2beed740ef
Updated•5 years ago
|
Updated•5 years ago
|
Description
•