Changeset 291267 in webkit


Ignore:
Timestamp:
Mar 15, 2022 12:19:08 AM (4 months ago)
Author:
youenn@apple.com
Message:

AudioContext stops playing when minimizing or moving the macOS Safari window to the background.
https://bugs.webkit.org/show_bug.cgi?id=231105
<rdar://problem/83889697>

Reviewed by Eric Carlson.

Source/WebCore:

AudioContext was stopped when minimizing windows if not playing audio as a way to reduce CPU usage.
But this is visible to users (if AudioContext produces audio through a track) or to web pages (use of audio worklet or script processor node).
Remove that code.
Small refactoring to remove isOfflineContext checks that can only be false in AudioContext.

Covered by existing tests.

  • Modules/webaudio/AudioContext.cpp:
  • Modules/webaudio/AudioContext.h:

LayoutTests:

Use internals API to be working on iOS as well (this does not trigger enterBackground code path).

  • webaudio/silent-audio-interrupted-in-background-expected.txt:
  • webaudio/silent-audio-interrupted-in-background.html:
Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r291266 r291267  
     12022-03-15  Youenn Fablet  <youenn@apple.com>
     2
     3        AudioContext stops playing when minimizing or moving the macOS Safari window to the background.
     4        https://bugs.webkit.org/show_bug.cgi?id=231105
     5        <rdar://problem/83889697>
     6
     7        Reviewed by Eric Carlson.
     8
     9        Use internals API to be working on iOS as well (this does not trigger enterBackground code path).
     10
     11        * webaudio/silent-audio-interrupted-in-background-expected.txt:
     12        * webaudio/silent-audio-interrupted-in-background.html:
     13
    1142022-03-14  Lauro Moura  <lmoura@igalia.com>
    215
  • trunk/LayoutTests/webaudio/silent-audio-interrupted-in-background-expected.txt

    r214721 r291267  
    1 Tests that silent WebAudio rendering gets interrupted in hidden pages.
     1Tests silent WebAudio rendering in hidden pages.
    22
    33On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
     
    66PASS context.state became 'running'
    77* Setting page visibility to hidden
    8 PASS context.state became 'interrupted'
     8PASS document.hidden is true
     9PASS context.state is 'running'
    910* Setting page visibility to visible
    10 PASS context.state became 'running'
     11PASS document.hidden is false
     12PASS context.state is 'running'
    1113PASS successfullyParsed is true
    1214
  • trunk/LayoutTests/webaudio/silent-audio-interrupted-in-background.html

    r267504 r291267  
    44<script src="../resources/js-test-pre.js"></script>
    55<script>
    6 description("Tests that silent WebAudio rendering gets interrupted in hidden pages.");
     6description("Tests silent WebAudio rendering in hidden pages.");
    77jsTestIsAsync = true;
    88
    9 document.onvisibilitychange = function() {
    10     if (document.hidden) {
    11         shouldBecomeEqual("context.state", "'interrupted'", showPage);
    12     } else {
    13         shouldBecomeEqual("context.state", "'running'", finishJSTest);
     9let counter = 0;
     10document.onvisibilitychange = async function() {
     11    if (!counter) {
     12         counter = 1;
     13         shouldBeTrue("document.hidden");
     14         shouldBe("context.state", "'running'");
     15         showPage();
     16         return;
    1417    }
     18    shouldBeFalse("document.hidden");
     19    shouldBe("context.state", "'running'");
     20    finishJSTest();
    1521}
    1622
     
    1824{
    1925    debug("* Setting page visibility to visible");
    20     if (window.testRunner)
    21         testRunner.setPageVisibility("visible");
     26    if (window.internals)
     27        internals.setPageVisibility(true);
    2228}
    2329
     
    2531{
    2632    debug("* Setting page visibility to hidden");
    27     if (window.testRunner)
    28         testRunner.setPageVisibility("hidden");
     33    if (window.internals)
     34        internals.setPageVisibility(false);
    2935}
    3036
  • trunk/Source/WebCore/ChangeLog

    r291261 r291267  
     12022-03-15  Youenn Fablet  <youenn@apple.com>
     2
     3        AudioContext stops playing when minimizing or moving the macOS Safari window to the background.
     4        https://bugs.webkit.org/show_bug.cgi?id=231105
     5        <rdar://problem/83889697>
     6
     7        Reviewed by Eric Carlson.
     8
     9        AudioContext was stopped when minimizing windows if not playing audio as a way to reduce CPU usage.
     10        But this is visible to users (if AudioContext produces audio through a track) or to web pages (use of audio worklet or script processor node).
     11        Remove that code.
     12        Small refactoring to remove isOfflineContext checks that can only be false in AudioContext.
     13
     14        Covered by existing tests.
     15
     16        * Modules/webaudio/AudioContext.cpp:
     17        * Modules/webaudio/AudioContext.h:
     18
    1192022-03-14  Wenson Hsieh  <wenson_hsieh@apple.com>
    220
  • trunk/Source/WebCore/Modules/webaudio/AudioContext.cpp

    r286918 r291267  
    123123
    124124    document.addAudioProducer(*this);
    125     document.registerForVisibilityStateChangedCallbacks(*this);
    126125
    127126    // Unlike OfflineAudioContext, AudioContext does not require calling resume() to start rendering.
     
    149148AudioContext::~AudioContext()
    150149{
    151     if (!isOfflineContext() && scriptExecutionContext()) {
    152         document()->removeAudioProducer(*this);
    153         document()->unregisterForVisibilityStateChangedCallbacks(*this);
    154     }
     150    if (auto* document = this->document())
     151        document->removeAudioProducer(*this);
    155152}
    156153
     
    194191void AudioContext::close(DOMPromiseDeferred<void>&& promise)
    195192{
    196     if (isOfflineContext() || isStopped()) {
     193    if (isStopped()) {
    197194        promise.reject(InvalidStateError);
    198195        return;
     
    217214void AudioContext::suspendRendering(DOMPromiseDeferred<void>&& promise)
    218215{
    219     if (isOfflineContext()) {
    220         promise.reject(Exception { InvalidStateError, "Cannot call suspend() on an OfflineAudioContext"_s });
    221         return;
    222     }
    223 
    224216    if (isStopped() || state() == State::Closed) {
    225217        promise.reject(Exception { InvalidStateError, "Context is closed"_s });
     
    248240void AudioContext::resumeRendering(DOMPromiseDeferred<void>&& promise)
    249241{
    250     if (isOfflineContext()) {
    251         promise.reject(Exception { InvalidStateError, "Cannot call resume() on an OfflineAudioContext"_s });
    252         return;
    253     }
    254 
    255242    if (isStopped() || state() == State::Closed) {
    256243        promise.reject(Exception { InvalidStateError, "Context is closed"_s });
     
    417404}
    418405
    419 void AudioContext::visibilityStateChanged()
    420 {
    421     // Do not suspend if audio is audible.
    422     if (!document() || mediaState() == MediaProducerMediaState::IsPlayingAudio || isStopped())
    423         return;
    424 
    425     if (document()->hidden()) {
    426         if (state() == State::Running) {
    427             ALWAYS_LOG(LOGIDENTIFIER, "Suspending playback after going to the background");
    428             m_mediaSession->beginInterruption(PlatformMediaSession::EnteringBackground);
    429         }
    430     } else {
    431         if (state() == State::Interrupted) {
    432             ALWAYS_LOG(LOGIDENTIFIER, "Resuming playback after entering foreground");
    433             m_mediaSession->endInterruption(PlatformMediaSession::MayResumePlaying);
    434         }
    435     }
    436 }
    437 
    438406void AudioContext::suspend(ReasonForSuspension)
    439407{
  • trunk/Source/WebCore/Modules/webaudio/AudioContext.h

    r284173 r291267  
    3131#include "MediaProducer.h"
    3232#include "PlatformMediaSession.h"
    33 #include "VisibilityChangeClient.h"
    3433#include <wtf/UniqueRef.h>
    3534
     
    4948    , public MediaProducer
    5049    , public MediaCanStartListener
    51     , private PlatformMediaSessionClient
    52     , private VisibilityChangeClient {
     50    , private PlatformMediaSessionClient {
    5351    WTF_MAKE_ISO_ALLOCATED(AudioContext);
    5452public:
     
    137135    void mediaCanStart(Document&) final;
    138136
    139     // VisibilityChangeClient
    140     void visibilityStateChanged() final;
    141 
    142137    // ActiveDOMObject
    143138    const char* activeDOMObjectName() const final;
Note: See TracChangeset for help on using the changeset viewer.