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:Martin Šrámek <msramek@chromium.org> Reviewed-by:
Matt Falkenhagen <falken@chromium.org> Reviewed-by:
Takashi Toyoshima <toyoshim@chromium.org> Reviewed-by:
Dale Curtis <dalecurtis@chromium.org> Commit-Queue: Lingqi Chi <lingqi@chromium.org> Cr-Commit-Position: refs/heads/main@{#915906}
Loading
Please register or sign in to comment