LibWeb+LibWebView+WebContent: Support muting an entire page

This adds an IPC for chromes to mute a tab. When muted, we trigger an
internal volume change notification and indicate that the user agent has
overriden the media volume.
This commit is contained in:
Timothy Flynn 2024-03-30 09:41:15 -04:00 committed by Andreas Kling
commit f61f55d397
Notes: sideshowbarker 2024-07-17 02:22:23 +09:00
10 changed files with 68 additions and 2 deletions

View file

@ -6,6 +6,8 @@
#pragma once
#include <AK/Assertions.h>
namespace Web::HTML {
enum class AudioPlayState {
@ -13,4 +15,21 @@ enum class AudioPlayState {
Playing,
};
enum class MuteState {
Muted,
Unmuted,
};
constexpr MuteState invert_mute_state(MuteState mute_state)
{
switch (mute_state) {
case MuteState::Muted:
return MuteState::Unmuted;
case MuteState::Unmuted:
return MuteState::Muted;
}
VERIFY_NOT_REACHED();
}
}

View file

@ -438,11 +438,18 @@ void HTMLMediaElement::volume_or_muted_attribute_changed()
on_volume_change();
}
void HTMLMediaElement::page_mute_state_changed(Badge<Page>)
{
on_volume_change();
}
// https://html.spec.whatwg.org/multipage/media.html#effective-media-volume
double HTMLMediaElement::effective_media_volume() const
{
// FIXME 1. If the user has indicated that the user agent is to override the volume of the element, then return the
// volume desired by the user.
// 1. If the user has indicated that the user agent is to override the volume of the element, then return the
// volume desired by the user.
if (document().page().page_mute_state() == MuteState::Muted)
return 0.0;
// 2. If the element's audio output is muted, then return zero.
if (m_muted)

View file

@ -98,6 +98,8 @@ public:
bool muted() const { return m_muted; }
void set_muted(bool);
void page_mute_state_changed(Badge<Page>);
double effective_media_volume() const;
JS::NonnullGCPtr<AudioTrackList> audio_tracks() const { return *m_audio_tracks; }

View file

@ -470,6 +470,18 @@ WebIDL::ExceptionOr<void> Page::toggle_media_controls_state()
return {};
}
void Page::toggle_page_mute_state()
{
m_mute_state = HTML::invert_mute_state(m_mute_state);
for (auto media_id : m_media_elements) {
if (auto* node = DOM::Node::from_unique_id(media_id)) {
auto& media_element = verify_cast<HTML::HTMLMediaElement>(*node);
media_element.page_mute_state_changed({});
}
}
}
JS::GCPtr<HTML::HTMLMediaElement> Page::media_context_menu_element()
{
if (!m_media_context_menu_element_id.has_value())

View file

@ -167,6 +167,9 @@ public:
WebIDL::ExceptionOr<void> toggle_media_loop_state();
WebIDL::ExceptionOr<void> toggle_media_controls_state();
HTML::MuteState page_mute_state() const { return m_mute_state; }
void toggle_page_mute_state();
Optional<String> const& user_style() const { return m_user_style_sheet_source; }
void set_user_style(String source);
@ -210,6 +213,8 @@ private:
Vector<int> m_media_elements;
Optional<int> m_media_context_menu_element_id;
Web::HTML::MuteState m_mute_state { Web::HTML::MuteState::Unmuted };
Optional<String> m_user_style_sheet_source;
// https://html.spec.whatwg.org/multipage/system-state.html#pdf-viewer-supported

View file

@ -315,6 +315,12 @@ void ViewImplementation::toggle_media_controls_state()
client().async_toggle_media_controls_state(page_id());
}
void ViewImplementation::toggle_page_mute_state()
{
m_mute_state = Web::HTML::invert_mute_state(m_mute_state);
client().async_toggle_page_mute_state(page_id());
}
void ViewImplementation::did_change_audio_play_state(Badge<WebContentClient>, Web::HTML::AudioPlayState play_state)
{
bool state_changed = false;

View file

@ -102,6 +102,9 @@ public:
void toggle_media_loop_state();
void toggle_media_controls_state();
Web::HTML::MuteState page_mute_state() const { return m_mute_state; }
void toggle_page_mute_state();
void did_change_audio_play_state(Badge<WebContentClient>, Web::HTML::AudioPlayState);
Web::HTML::AudioPlayState audio_play_state() const { return m_audio_play_state; }
@ -261,6 +264,8 @@ protected:
Web::HTML::AudioPlayState m_audio_play_state { Web::HTML::AudioPlayState::Paused };
size_t m_number_of_elements_playing_audio { 0 };
Web::HTML::MuteState m_mute_state { Web::HTML::MuteState::Unmuted };
};
}

View file

@ -1072,6 +1072,12 @@ void ConnectionFromClient::toggle_media_controls_state(u64 page_id)
page->page().toggle_media_controls_state().release_value_but_fixme_should_propagate_errors();
}
void ConnectionFromClient::toggle_page_mute_state(u64 page_id)
{
if (auto page = this->page(page_id); page.has_value())
page->page().toggle_page_mute_state();
}
void ConnectionFromClient::set_user_style(u64 page_id, String const& source)
{
if (auto page = this->page(page_id); page.has_value())

View file

@ -111,6 +111,8 @@ private:
virtual void toggle_media_loop_state(u64 page_id) override;
virtual void toggle_media_controls_state(u64 page_id) override;
virtual void toggle_page_mute_state(u64 page_id) override;
virtual void set_user_style(u64 page_id, String const&) override;
virtual void enable_inspector_prototype(u64 page_id) override;

View file

@ -98,6 +98,8 @@ endpoint WebContentServer
toggle_media_loop_state(u64 page_id) =|
toggle_media_controls_state(u64 page_id) =|
toggle_page_mute_state(u64 page_id) =|
set_user_style(u64 page_id, String source) =|
enable_inspector_prototype(u64 page_id) =|