Skip to content
Commit 1e30a77f authored by Lingqi Chi's avatar Lingqi Chi Committed by Chromium LUCI CQ
Browse files

Prerender: Cancel prerendering if it requests audio output devices

This CL fixes the endless hanging bug that occurs when prerendering
documents executing `new AudioContext()`. The root cause of this bug
can be found in https://crbug.com/1233349.

It fixes this bug by introducing a new class named RestrictedModeCore to
RenderFrameAudioOutputStreamFactory. This class is used in replacement
with RenderFrameAudioOutputStreamFactory::Core and performs
message-level Mojo capability control during prerendering.

For normal pages, it doesn't change the current design.
For prerendering pages, a general workflow be like:
1.  [UI] RenderFrameHostImpl(RFHI) is requested to bind the receiver end
    of mojom::RendererAudioOutputStreamFactory.
2.  [UI] RFHI creates a new RenderFrameAudioOutputStreamFactory(RFAOSF)
    instance, and initialize it in the restricted mode.
3.  [UI] In the restricted mode, RFAOSF creates a RestrictedModeCore
    instance, and passes the receiver to it.
    Here, the behavior varies from a normal frame. In a normal frame,
    the receiver will be sent to the IO thread and will be bound with
    `core_`.
4.  [UI] RestrictedModeCore binds the receiver. It is responsible for
    handling Mojo messages during prerendering.
5.1 [UI] If the prerendering document requests for output devices:
    A message-level capability control is applied. Browser will cancel
    prerendering.
    Stop here.
    ********

5.2 If it doesn't: It can be activated later.
6.  [UI] RFHI knows that it is about to be activated. It informs
    RFAOSF by calling RFAOSF::ReleaseRestriction.
7.  [UI] RFAOSF asks RestrictedModeCore to unbind its receiver, and
    sends this receiver to the IO thread. core will bind the receiver
    there.
    From now on RestrictedModeCore no longer performs message control.
8.  [IO] Core binds the receiver. Now it can process Mojo messages.
    Everything is back to normal.

- Why Mojo capability control cannot cover this case:
  - We cannot cancel on binding RendererAudioOutputStreamFactory. This
    interface is requested for all frames regardless of whether it will
    be used.
  - We cannot defer it. One sync API(AudioContext()) relies on this
    interface and assumes the interface is always connected before
    using.
    Based on this assumption, it blocks the renderer's main thread when
    sending messages over this API. Deferring this API results in
    deadlock. See the issue description for more information.
  - We decide not to grant it for now. We may want to allow prerenders
    to request output devices and disallow them to create output streams
    after we gain a better understanding of audio APIs.

- Why the new class is needed.
  Otherwise it would be problematic if we want to check the prerendering
  state while processing Mojo messages. Without this class, the receiver
  will sent to the IO thread, while the main control flow of
  prerendering is running on the UI thread.

Bug: 1233349
Change-Id: I34a08643235a4ef285fef55fb9e20b90a8ae1b36
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3081002


Reviewed-by: default avatarMartin Šrámek <msramek@chromium.org>
Reviewed-by: default avatarMatt Falkenhagen <falken@chromium.org>
Reviewed-by: default avatarTakashi Toyoshima <toyoshim@chromium.org>
Reviewed-by: default avatarDale Curtis <dalecurtis@chromium.org>
Commit-Queue: Lingqi Chi <lingqi@chromium.org>
Cr-Commit-Position: refs/heads/main@{#915906}
parent d9fbd533
Loading
Loading
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment