Automatic update from web-platform-tests
requestIdleCallback: Fix idle period brittleness
This CL fixes a few issues with idle periods not starting when they
should due to not requesting the `BeginMainFrameNotExpected` signals
from the compositor.
Idle periods, which requestIdleCallback tasks are confined to run in,
are triggered by:
1. Frame production (`BeginMainFrame` from any source). We can start a
short idle period after every `BeginMainFrame` (if there are idle
tasks and time remaining).
2. `BeginMainFrameNotExpected` signals from the compositor. These are
requested through `LayerTreeHost` via `PageSchedulerImpl` --> `Page`
--> `ChromeClient` --> ... These signals are necessary to start
idle periods after frame production stops.
There are a couple scenarios where we receive `BeginMainFrame`s signals
from a `WidgetScheduler`, but not `BeginMainFrameNotExpected` signals,
which causes us to stop running idle tasks.
First, idle tasks might not run in OOPIFs. There's an early return in
`Page::RequestBeginMainFrameNotExpected()` if the main frame is not
local, which means if a render process holds a single OOPIF, the idle period-starting signals from the compositor are never sent, and idle
tasks might never run. Note: rendering will temporarily unblock idle
tasks, because of (1) above, e.g. mousemove in the frame (see
crbug.com/40785325).
Second, idle tasks might not run if a popup is showing (e.g. date
picker). See crbug.com/378738907 for an example. The root cause here is
that the `WebPagePopupImpl`'s `ChromeClient` doesn't implement `RequestBeginFrameNotExpected()`.
This CL fixes these issues by refactoring how the signals are requested from the compositor, and by ensuring we always request the signals from any `BeginMainFrame` source:
- Add `WidgetScheduler::Delegate`, through which the signals are
requested. The signals are received via `WidgetScheduler`, so this
simplifies the existing plumbing. `WidgetBase`, which is the
creator/owner of `WidgetScheduler`, implements the `Delegate`
interface.
- `WidgetScheduler` stores a raw_ptr to the `Delegate`, which is
cleared in `WillShutdown()` (newly added, called from `WidgetBase`)
- `MainThreadSchedulerImpl` tracks the non-shutdown widget schedulers
(entries are removed on `WillShutdown()`). The MTSI requests the
signals from each `WidgetScheduler`.
- If we're already receiving the signals from a `WidgetScheduler` and
a new `WidgetScheduler` is created, immediately request the signals
to keep things in sync. This also handles the case where idle tasks
are posted prior to any `WidgetScheduler` being created (unlikely,
but possible since idle tasks can be queued outside of rIC).
- On `Shutdown()`, make sure the we don't stall idle periods because
the page being closed was in a short idle period.
Additionally:
- This is behind a kill switch, just in case this breaks something
- This adds a wpt test for the OOPIF case, which times out locally
without the fix
Fixed: 40785325, 378738907
Change-Id: I616c3fbf672202aa5bb3b4ebf26c011ac5f26a24
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6006337
Reviewed-by: Stefan Zager <szager@chromium.org>
Commit-Queue: Scott Haseley <shaseley@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1437839}
--
wpt-commits: f082d92f1da8860a13d0b57cc777ef1ef89d64d4
wpt-pr: 51587
20 lines
619 B
HTML
20 lines
619 B
HTML
<!doctype html>
|
|
<title>window.requestIdleCallback in a cross-origin iframe.</title>
|
|
<script src="/resources/testharness.js"></script>
|
|
<script src="/resources/testharnessreport.js"></script>
|
|
<script>
|
|
async_test(t => {
|
|
onload = function() {
|
|
const iframe = document.createElement('iframe');
|
|
iframe.src = location.href.replace('://', '://www1.')
|
|
.replace('callback-iframe-different-origin', 'resources/child');
|
|
document.body.appendChild(iframe);
|
|
};
|
|
|
|
onmessage = function(e) {
|
|
assert_equals(e.data, 'done');
|
|
t.done();
|
|
}
|
|
}, 'Check that idle tasks run in a cross-origin iframe');
|
|
</script>
|