diff --git a/media/audio/win/audio_ducker_win.cc b/media/audio/win/audio_ducker_win.cc index 0afab9a6eb4f5..def972f78512c 100644 --- a/media/audio/win/audio_ducker_win.cc +++ b/media/audio/win/audio_ducker_win.cc @@ -121,13 +121,13 @@ void AudioDuckerWin::StartDuckingOtherWindowsApplications() { if (!session_creation_observer_) { session_creation_observer_ = - std::make_unique( + Microsoft::WRL::Make( base::BindPostTaskToCurrentDefault(base::BindRepeating( &AudioDuckerWin::DuckNewAudioSessionsIfNecessary, weak_factory_.GetWeakPtr()))); } ducked_audio_session_manager_->RegisterSessionNotification( - session_creation_observer_.get()); + session_creation_observer_.Get()); // `base::Unretained()` is safe here because this callback is called // synchronously. @@ -151,7 +151,7 @@ void AudioDuckerWin::StopDuckingOtherWindowsApplications() { if (ducked_audio_session_manager_) { CHECK(session_creation_observer_); ducked_audio_session_manager_->UnregisterSessionNotification( - session_creation_observer_.get()); + session_creation_observer_.Get()); ducked_audio_session_manager_.Reset(); } return; @@ -174,7 +174,7 @@ void AudioDuckerWin::StopDuckingOtherWindowsApplications() { ducked_applications_.clear(); ducked_audio_session_manager_->UnregisterSessionNotification( - session_creation_observer_.get()); + session_creation_observer_.Get()); ducked_audio_session_manager_.Reset(); } diff --git a/media/audio/win/audio_ducker_win.h b/media/audio/win/audio_ducker_win.h index 691dc5e86f9ad..988f166774993 100644 --- a/media/audio/win/audio_ducker_win.h +++ b/media/audio/win/audio_ducker_win.h @@ -57,8 +57,12 @@ class MEDIA_EXPORT AudioDuckerWin { // Called when the system notifies us of a new audio session being created. void DuckNewAudioSessionsIfNecessary(); - // Listens for audio session creation notifications from the OS. - std::unique_ptr session_creation_observer_; + // Listens for audio session creation notifications from the OS. Held via + // ComPtr (not unique_ptr) because Windows' CAudioSessionManager also holds a + // COM reference for the duration of in-flight OnSessionCreated() callbacks on + // the MM thread; the object must outlive both owners. + Microsoft::WRL::ComPtr + session_creation_observer_; // Used to determine which applications we should duck. ShouldDuckProcessCallback should_duck_process_callback_; diff --git a/media/audio/win/audio_session_creation_observer_win.cc b/media/audio/win/audio_session_creation_observer_win.cc index 4fdf90e2dfed1..3df84ef3219d8 100644 --- a/media/audio/win/audio_session_creation_observer_win.cc +++ b/media/audio/win/audio_session_creation_observer_win.cc @@ -16,25 +16,6 @@ AudioSessionCreationObserverWin::AudioSessionCreationObserverWin( AudioSessionCreationObserverWin::~AudioSessionCreationObserverWin() = default; -ULONG AudioSessionCreationObserverWin::AddRef() { - return 1; -} - -ULONG AudioSessionCreationObserverWin::Release() { - return 1; -} - -HRESULT AudioSessionCreationObserverWin::QueryInterface(REFIID iid, - void** object) { - if (iid == IID_IUnknown || iid == __uuidof(IAudioSessionNotification)) { - *object = static_cast(this); - return S_OK; - } - - *object = nullptr; - return E_NOINTERFACE; -} - HRESULT AudioSessionCreationObserverWin::OnSessionCreated( IAudioSessionControl* session) { session_created_cb_.Run(); diff --git a/media/audio/win/audio_session_creation_observer_win.h b/media/audio/win/audio_session_creation_observer_win.h index 54982dfdf635a..73a3a25a1d7bb 100644 --- a/media/audio/win/audio_session_creation_observer_win.h +++ b/media/audio/win/audio_session_creation_observer_win.h @@ -6,6 +6,8 @@ #define MEDIA_AUDIO_WIN_AUDIO_SESSION_CREATION_OBSERVER_WIN_H_ #include +#include +#include #include "base/functional/callback.h" @@ -13,7 +15,18 @@ namespace media { // Calls the given callback when notified by the IAudioSessionManager2 that an // audio session was created. -class AudioSessionCreationObserverWin : public IAudioSessionNotification { +// +// Uses WRL::RuntimeClass so that AddRef()/Release() perform real COM +// refcounting. Windows' CAudioSessionManager AddRef()s registered notification +// clients for the duration of an in-flight OnSessionCreated() dispatch on the +// MM thread; with stubbed refcounting the object could be freed underneath an +// in-flight callback. Owners must hold this via Microsoft::WRL::ComPtr (created +// with Microsoft::WRL::Make<>) so the object survives until both Chromium and +// Windows have released their references. +class AudioSessionCreationObserverWin + : public Microsoft::WRL::RuntimeClass< + Microsoft::WRL::RuntimeClassFlags, + IAudioSessionNotification> { public: // `session_created_callback` is called when the system notifies us of a new // audio session via `OnSessionCreated()`. @@ -23,12 +36,9 @@ class AudioSessionCreationObserverWin : public IAudioSessionNotification { delete; AudioSessionCreationObserverWin& operator=( const AudioSessionCreationObserverWin&) = delete; - virtual ~AudioSessionCreationObserverWin(); + ~AudioSessionCreationObserverWin() override; // IAudioSessionNotification: - IFACEMETHODIMP_(ULONG) AddRef() override; - IFACEMETHODIMP_(ULONG) Release() override; - IFACEMETHODIMP QueryInterface(REFIID iid, void** object) override; IFACEMETHODIMP OnSessionCreated(IAudioSessionControl* session) override; private: