0

[video pip] Add progress bar to 2024 UI

This CL adds a progress bar to the video picture-in-picture controls.
It reuses the existing MediaProgressView element for this, and routes
the commands to the VideoPictureInPictureWindowController.

Bug: 360357715
Change-Id: I209d3d7a0c045fe00ec972861763789ce8c6aa2e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5912245
Reviewed-by: Peter Kvitek <kvitekp@chromium.org>
Reviewed-by: Tommy Steimel <steimel@chromium.org>
Reviewed-by: Avi Drissman <avi@chromium.org>
Commit-Queue: Tommy Steimel <steimel@chromium.org>
Reviewed-by: Fr <beaufort.francois@gmail.com>
Cr-Commit-Position: refs/heads/main@{#1378645}
This commit is contained in:
Tommy Steimel
2024-11-05 22:06:08 +00:00
committed by Chromium LUCI CQ
parent a97a6a9628
commit b1c91d9b6a
14 changed files with 246 additions and 12 deletions

@ -103,6 +103,8 @@ class MockVideoPictureInPictureWindowController
MOCK_METHOD0(GetWebContents, content::WebContents*());
MOCK_METHOD0(GetChildWebContents, content::WebContents*());
MOCK_METHOD0(TogglePlayPause, bool());
MOCK_METHOD0(Play, void());
MOCK_METHOD0(Pause, void());
MOCK_METHOD0(SkipAd, void());
MOCK_METHOD0(NextTrack, void());
MOCK_METHOD0(PreviousTrack, void());
@ -111,6 +113,7 @@ class MockVideoPictureInPictureWindowController
MOCK_METHOD0(HangUp, void());
MOCK_METHOD0(PreviousSlide, void());
MOCK_METHOD0(NextSlide, void());
MOCK_METHOD1(SeekTo, void(base::TimeDelta time));
MOCK_CONST_METHOD0(GetSourceBounds, const gfx::Rect&());
MOCK_METHOD0(GetWindowBounds, std::optional<gfx::Rect>());
MOCK_METHOD0(GetOrigin, std::optional<url::Origin>());

@ -79,6 +79,7 @@ class OverlayWindowAndroid : public content::VideoOverlayWindow,
void SetHangUpButtonVisibility(bool is_visible) override;
void SetNextSlideButtonVisibility(bool is_visible) override;
void SetPreviousSlideButtonVisibility(bool is_visible) override;
void SetMediaPosition(const media_session::MediaPosition&) override {}
void SetSurfaceId(const viz::SurfaceId& surface_id) override;
private:

@ -597,8 +597,13 @@ void VideoOverlayWindowViews::OnMouseEvent(ui::MouseEvent* event) {
// On Windows, ui::EventType::kMouseExited is triggered when hovering over
// the media controls because of the HitTest. This check ensures the
// controls are visible if the mouse is still over the window.
// We also check that the user isn't currently dragging the progress bar,
// since setting visibility to false during the drag will prevent the drag
// from functioning properly (and we'll lose the drag end).
const bool should_update_control_visibility =
!GetWindowBackgroundView()->bounds().Contains(event->location());
!GetWindowBackgroundView()->bounds().Contains(event->location()) &&
progress_view_drag_state_ ==
global_media_controls::DragState::kDragEnded;
if (should_update_control_visibility)
UpdateControlsVisibility(false);
break;
@ -788,7 +793,8 @@ bool VideoOverlayWindowViews::ControlsHitTestContainsPoint(
GetToggleCameraButtonBounds().Contains(point) ||
GetHangUpButtonBounds().Contains(point) ||
GetPreviousSlideControlsBounds().Contains(point) ||
GetNextSlideControlsBounds().Contains(point)) {
GetNextSlideControlsBounds().Contains(point) ||
GetProgressViewBounds().Contains(point)) {
return true;
}
return false;
@ -837,6 +843,7 @@ void VideoOverlayWindowViews::SetUpViews() {
std::unique_ptr<ToggleMicrophoneButton> toggle_microphone_button;
std::unique_ptr<ToggleCameraButton> toggle_camera_button;
std::unique_ptr<HangUpButton> hang_up_button;
std::unique_ptr<global_media_controls::MediaProgressView> progress_view;
if (Use2024UI()) {
play_pause_controls_view->SetSize(
@ -887,6 +894,30 @@ void VideoOverlayWindowViews::SetUpViews() {
l10n_util::GetStringUTF16(
IDS_PICTURE_IN_PICTURE_NEXT_TRACK_CONTROL_ACCESSIBLE_TEXT));
next_track_controls_view->SetSize(kPreviousNextButtonSize);
// `base::Unretained()` is okay here since we own the progress view.
progress_view = std::make_unique<global_media_controls::MediaProgressView>(
/*use_squiggly_line=*/false,
/*playing_foreground_color_id=*/ui::kColorSysPrimary,
/*playing_background_color_id=*/ui::kColorSysStateDisabledContainer,
/*paused_foreground_color_id=*/ui::kColorSysStateDisabledContainer,
/*paused_background_color_id=*/ui::kColorSysStateDisabledContainer,
/*focus_ring_color_id=*/ui::kColorSysStateFocusRing,
/*drag_state_change_callback=*/
base::BindRepeating(
&VideoOverlayWindowViews::OnProgressDragStateChanged,
base::Unretained(this)),
/*playback_state_change_for_dragging_callback=*/
base::BindRepeating(
&VideoOverlayWindowViews::ChangePlaybackStateForProgressDrag,
base::Unretained(this)),
/*seek_callback=*/
base::BindRepeating(
&VideoOverlayWindowViews::SeekForProgressBarInteraction,
base::Unretained(this)),
/*on_update_progress_callback=*/
base::BindRepeating(
&VideoOverlayWindowViews::OnProgressViewUpdateCurrentTime,
base::Unretained(this)));
} else {
back_to_tab_label_button =
std::make_unique<BackToTabLabelButton>(base::BindRepeating(
@ -1025,7 +1056,11 @@ void VideoOverlayWindowViews::SetUpViews() {
next_track_controls_view->layer()->SetFillsBoundsOpaquely(false);
next_track_controls_view->layer()->SetName("NextTrackControlsView");
if (!Use2024UI()) {
if (Use2024UI()) {
progress_view->SetPaintToLayer(ui::LAYER_TEXTURED);
progress_view->layer()->SetFillsBoundsOpaquely(false);
progress_view->layer()->SetName("ProgressView");
} else {
// views::View that holds the skip-ad label button.
// -------------------------
skip_ad_controls_view->SetPaintToLayer(ui::LAYER_TEXTURED);
@ -1089,6 +1124,11 @@ void VideoOverlayWindowViews::SetUpViews() {
play_pause_controls_view_ = controls_container_view->AddChildView(
std::move(play_pause_controls_view));
if (Use2024UI()) {
progress_view_ =
controls_container_view->AddChildView(std::move(progress_view));
}
next_track_controls_view_ = controls_container_view->AddChildView(
std::move(next_track_controls_view));
if (!Use2024UI()) {
@ -1203,6 +1243,7 @@ void VideoOverlayWindowViews::OnUpdateControlsBounds() {
if (Use2024UI()) {
constexpr int kTopControlsHeight = 34;
constexpr int kBottomControlsHeight = 64;
constexpr int kProgressBarHeight = 26;
constexpr int kControlHorizontalMargin = 8;
constexpr int kBottomControlsHorizontalMargin = 8;
constexpr int kBottomControlsVerticalMargin = 4;
@ -1245,6 +1286,28 @@ void VideoOverlayWindowViews::OnUpdateControlsBounds() {
kPreviousNextButtonSize.width()),
bottom_controls_bounds.y() + kBottomControlsVerticalMargin});
// The progress bars should take up all the space that is left after the
// previous and next buttons. Here we calculate how much horizontal space
// one of those buttons takes up and use that to calculate the width and x
// position of the progress view.
constexpr int kPreviousNextTrackWidthPlusHorizontalMargins =
kBottomControlsHorizontalMargin + (2 * kControlHorizontalMargin) +
kPreviousNextButtonSize.width();
progress_view_->SetPosition(
{bottom_controls_bounds.x() +
kPreviousNextTrackWidthPlusHorizontalMargins,
bottom_controls_bounds.y() + kBottomControlsVerticalMargin});
progress_view_->SetSize(
{bounds.width() - (2 * kPreviousNextTrackWidthPlusHorizontalMargins),
kProgressBarHeight});
// The play/pause button should not be visible while dragging the progress
// bar.
play_pause_controls_view_->SetVisible(
show_play_pause_button_ &&
progress_view_drag_state_ !=
global_media_controls::DragState::kDragStarted);
// The previous and next track buttons are always visible, but disabled if
// there is no action handler for them.
previous_track_controls_view_->SetEnabled(show_previous_track_button_);
@ -1573,6 +1636,15 @@ void VideoOverlayWindowViews::SetHangUpButtonVisibility(bool is_visible) {
UpdateControlsBounds();
}
void VideoOverlayWindowViews::SetMediaPosition(
const media_session::MediaPosition& position) {
if (!Use2024UI()) {
return;
}
position_ = position;
progress_view_->UpdateProgress(position);
}
void VideoOverlayWindowViews::SetSurfaceId(const viz::SurfaceId& surface_id) {
// The PiP window may have a previous surface set. If the window stays open
// since then, we need to unregister the previous frame sink; otherwise the
@ -1741,6 +1813,13 @@ gfx::Rect VideoOverlayWindowViews::GetNextSlideControlsBounds() {
return next_slide_controls_view_->GetMirroredBounds();
}
gfx::Rect VideoOverlayWindowViews::GetProgressViewBounds() {
if (!Use2024UI()) {
return gfx::Rect();
}
return progress_view_->GetMirroredBounds();
}
#if BUILDFLAG(IS_CHROMEOS)
int VideoOverlayWindowViews::GetResizeHTComponent() const {
return resize_handle_view_->GetHTComponent();
@ -1808,6 +1887,11 @@ VideoOverlayWindowViews::previous_slide_controls_view_for_testing() const {
return previous_slide_controls_view_;
}
global_media_controls::MediaProgressView*
VideoOverlayWindowViews::progress_view_for_testing() const {
return progress_view_;
}
CloseImageButton* VideoOverlayWindowViews::close_button_for_testing() const {
return close_controls_view_;
}
@ -1870,3 +1954,31 @@ void VideoOverlayWindowViews::RemoveOverlayViewIfExists() {
OnSizeConstraintsChanged();
}
}
void VideoOverlayWindowViews::OnProgressDragStateChanged(
global_media_controls::DragState drag_state) {
progress_view_drag_state_ = drag_state;
OnUpdateControlsBounds();
}
void VideoOverlayWindowViews::ChangePlaybackStateForProgressDrag(
global_media_controls::PlaybackStateChangeForDragging
playback_state_change) {
if (playback_state_change ==
global_media_controls::PlaybackStateChangeForDragging::
kPauseForDraggingStarted) {
controller_->Pause();
} else {
controller_->Play();
}
}
void VideoOverlayWindowViews::SeekForProgressBarInteraction(
double seek_progress) {
controller_->SeekTo(seek_progress * position_.duration());
}
void VideoOverlayWindowViews::OnProgressViewUpdateCurrentTime(
base::TimeDelta current_time) {
// TODO(crbug.com/360357715): Update current time view once it exists.
}

@ -11,6 +11,7 @@
#include "base/timer/timer.h"
#include "chrome/browser/picture_in_picture/auto_pip_setting_overlay_view.h"
#include "chromeos/ui/frame/highlight_border_overlay.h"
#include "components/global_media_controls/public/views/media_progress_view.h"
#include "content/public/browser/overlay_window.h"
#include "content/public/browser/video_picture_in_picture_window_controller.h"
#include "ui/display/display.h"
@ -78,6 +79,7 @@ class VideoOverlayWindowViews : public content::VideoOverlayWindow,
void SetHangUpButtonVisibility(bool is_visible) override;
void SetPreviousSlideButtonVisibility(bool is_visible) override;
void SetNextSlideButtonVisibility(bool is_visible) override;
void SetMediaPosition(const media_session::MediaPosition& position) override;
void SetSurfaceId(const viz::SurfaceId& surface_id) override;
// views::Widget:
@ -154,6 +156,7 @@ class VideoOverlayWindowViews : public content::VideoOverlayWindow,
gfx::Rect GetHangUpButtonBounds();
gfx::Rect GetPreviousSlideControlsBounds();
gfx::Rect GetNextSlideControlsBounds();
gfx::Rect GetProgressViewBounds();
PlaybackImageButton* play_pause_controls_view_for_testing() const;
SimpleOverlayWindowImageButton* next_track_controls_view_for_testing() const;
@ -166,6 +169,7 @@ class VideoOverlayWindowViews : public content::VideoOverlayWindow,
SimpleOverlayWindowImageButton* next_slide_controls_view_for_testing() const;
SimpleOverlayWindowImageButton* previous_slide_controls_view_for_testing()
const;
global_media_controls::MediaProgressView* progress_view_for_testing() const;
CloseImageButton* close_button_for_testing() const;
OverlayWindowMinimizeButton* minimize_button_for_testing() const;
OverlayWindowBackToTabButton* back_to_tab_button_for_testing() const;
@ -276,6 +280,13 @@ class VideoOverlayWindowViews : public content::VideoOverlayWindow,
// Removes the `overlay_view_` if it exists.
void RemoveOverlayViewIfExists();
void OnProgressDragStateChanged(global_media_controls::DragState drag_state);
void ChangePlaybackStateForProgressDrag(
global_media_controls::PlaybackStateChangeForDragging
playback_state_change);
void SeekForProgressBarInteraction(double seek_progress);
void OnProgressViewUpdateCurrentTime(base::TimeDelta current_time);
// Not owned; |controller_| owns |this|.
raw_ptr<content::VideoPictureInPictureWindowController> controller_;
@ -344,6 +355,7 @@ class VideoOverlayWindowViews : public content::VideoOverlayWindow,
raw_ptr<SimpleOverlayWindowImageButton> previous_slide_controls_view_ =
nullptr;
raw_ptr<SimpleOverlayWindowImageButton> next_slide_controls_view_ = nullptr;
raw_ptr<global_media_controls::MediaProgressView> progress_view_ = nullptr;
raw_ptr<AutoPipSettingOverlayView> overlay_view_ = nullptr;
#if BUILDFLAG(IS_CHROMEOS)
@ -388,6 +400,15 @@ class VideoOverlayWindowViews : public content::VideoOverlayWindow,
// case when Media Session "nextslide" action is handled by the website.
bool show_next_slide_button_ = false;
// Tracks whether or not the progress bar is currently being dragged by the
// user. Used to ensure that controls don't hide while dragging.
global_media_controls::DragState progress_view_drag_state_ =
global_media_controls::DragState::kDragEnded;
// Tracks the current position of media playback. Used for seeking to the
// proper time when the user interacts with the progress bar.
media_session::MediaPosition position_;
// Whether or not the current frame sink for the surface displayed in the
// |video_view_| is registered as the child of the overlay window frame sink.
bool has_registered_frame_sink_hierarchy_ = false;

@ -21,6 +21,7 @@
#include "chrome/browser/ui/views/overlay/simple_overlay_window_image_button.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/views/chrome_views_test_base.h"
#include "components/global_media_controls/public/views/media_progress_view.h"
#include "content/public/browser/overlay_window.h"
#include "content/public/browser/video_picture_in_picture_window_controller.h"
#include "content/public/browser/web_contents.h"
@ -105,6 +106,8 @@ class TestVideoPictureInPictureWindowController
content::WebContents* GetWebContents() override { return web_contents_; }
content::WebContents* GetChildWebContents() override { return nullptr; }
bool TogglePlayPause() override { return false; }
void Play() override {}
void Pause() override {}
void SkipAd() override {}
void NextTrack() override {}
void PreviousTrack() override {}
@ -113,6 +116,7 @@ class TestVideoPictureInPictureWindowController
void ToggleMicrophone() override {}
void ToggleCamera() override {}
void HangUp() override {}
MOCK_METHOD(void, SeekTo, (base::TimeDelta time));
const gfx::Rect& GetSourceBounds() const override { return source_bounds_; }
std::optional<gfx::Rect> GetWindowBounds() override { return std::nullopt; }
std::optional<url::Origin> GetOrigin() override { return std::nullopt; }
@ -728,6 +732,13 @@ TEST_F(VideoOverlayWindowViewsTest, IsTrackedByTheOcclusionObserver) {
EXPECT_EQ(0u, tracker->GetPictureInPictureWidgetsForTesting().size());
}
TEST_F(VideoOverlayWindowViewsTest, ProgressBarNotDrawnWhen2024UIIsDisabled) {
overlay_window().ForceControlsVisibleForTesting(true);
global_media_controls::MediaProgressView* progress_view =
overlay_window().progress_view_for_testing();
ASSERT_EQ(nullptr, progress_view);
}
class VideoOverlayWindowViewsWith2024UITest
: public VideoOverlayWindowViewsTest {
public:
@ -770,3 +781,23 @@ TEST_F(VideoOverlayWindowViewsWith2024UITest, ShowsBackToTabImageButton) {
button_clicker.NotifyClick(dummy_event);
testing::Mock::VerifyAndClearExpectations(&pip_window_controller());
}
TEST_F(VideoOverlayWindowViewsWith2024UITest, ProgressBarSeeksVideo) {
overlay_window().ForceControlsVisibleForTesting(true);
global_media_controls::MediaProgressView* progress_view =
overlay_window().progress_view_for_testing();
ASSERT_NE(nullptr, progress_view);
EXPECT_TRUE(progress_view->IsDrawn());
gfx::Point point(progress_view->width() / 2, progress_view->height() / 2);
ui::MouseEvent pressed_event(ui::EventType::kMousePressed, point, point,
ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
ui::EF_LEFT_MOUSE_BUTTON);
EXPECT_CALL(pip_window_controller(), SeekTo(_));
progress_view->OnMousePressed(pressed_event);
ui::MouseEvent released_event = ui::MouseEvent(
ui::EventType::kMouseReleased, point, point, ui::EventTimeForNow(),
ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
progress_view->OnMouseReleased(released_event);
}

@ -70,6 +70,7 @@ class TestVideoOverlayWindow : public VideoOverlayWindow {
void SetHangUpButtonVisibility(bool is_visible) override {}
void SetNextSlideButtonVisibility(bool is_visible) override {}
void SetPreviousSlideButtonVisibility(bool is_visible) override {}
void SetMediaPosition(const media_session::MediaPosition&) override {}
void SetSurfaceId(const viz::SurfaceId& surface_id) override {}
private:

@ -92,6 +92,7 @@ class TestOverlayWindow : public VideoOverlayWindow {
void SetHangUpButtonVisibility(bool is_visible) override {}
void SetNextSlideButtonVisibility(bool is_visible) override {}
void SetPreviousSlideButtonVisibility(bool is_visible) override {}
void SetMediaPosition(const media_session::MediaPosition&) override {}
void SetSurfaceId(const viz::SurfaceId& surface_id) override {}
private:

@ -72,6 +72,7 @@ class TestVideoOverlayWindow : public VideoOverlayWindow {
void SetHangUpButtonVisibility(bool is_visible) override {}
void SetNextSlideButtonVisibility(bool is_visible) override {}
void SetPreviousSlideButtonVisibility(bool is_visible) override {}
void SetMediaPosition(const media_session::MediaPosition&) override {}
void SetSurfaceId(const viz::SurfaceId& surface_id) override {}
const std::optional<PlaybackState>& playback_state() const {

@ -208,17 +208,30 @@ bool VideoPictureInPictureWindowControllerImpl::TogglePlayPause() {
DCHECK(active_session_);
if (IsPlayerActive()) {
if (media_session_action_pause_handled_) {
MediaSessionImpl::Get(web_contents())
->Suspend(MediaSession::SuspendType::kUI);
return true /* still playing */;
}
active_session_->GetMediaPlayerRemote()->RequestPause(
/*triggered_by_user=*/false);
return false /* paused */;
return PauseInternal();
}
return PlayInternal();
}
void VideoPictureInPictureWindowControllerImpl::Play() {
// This comes from the window, rather than the renderer, so we must actually
// have a window at this point.
DCHECK(window_);
DCHECK(active_session_);
PlayInternal();
}
void VideoPictureInPictureWindowControllerImpl::Pause() {
// This comes from the window, rather than the renderer, so we must actually
// have a window at this point.
DCHECK(window_);
DCHECK(active_session_);
PauseInternal();
}
bool VideoPictureInPictureWindowControllerImpl::PlayInternal() {
if (media_session_action_play_handled_) {
MediaSessionImpl::Get(web_contents())
->Resume(MediaSession::SuspendType::kUI);
@ -229,6 +242,18 @@ bool VideoPictureInPictureWindowControllerImpl::TogglePlayPause() {
return true /* playing */;
}
bool VideoPictureInPictureWindowControllerImpl::PauseInternal() {
if (media_session_action_pause_handled_) {
MediaSessionImpl::Get(web_contents())
->Suspend(MediaSession::SuspendType::kUI);
return true /* still playing */;
}
active_session_->GetMediaPlayerRemote()->RequestPause(
/*triggered_by_user=*/false);
return false /* paused */;
}
PictureInPictureResult VideoPictureInPictureWindowControllerImpl::StartSession(
PictureInPictureServiceImpl* service,
const MediaPlayerId& player_id,
@ -340,6 +365,12 @@ void VideoPictureInPictureWindowControllerImpl::HangUp() {
MediaSession::Get(web_contents())->HangUp();
}
void VideoPictureInPictureWindowControllerImpl::SeekTo(base::TimeDelta time) {
if (media_session_action_seek_to_handled_) {
MediaSession::Get(web_contents())->SeekTo(time);
}
}
void VideoPictureInPictureWindowControllerImpl::MediaSessionInfoChanged(
const media_session::mojom::MediaSessionInfoPtr& info) {
if (!info)
@ -395,6 +426,9 @@ void VideoPictureInPictureWindowControllerImpl::MediaSessionActionsChanged(
media_session_action_next_slide_handled_ =
actions.find(media_session::mojom::MediaSessionAction::kNextSlide) !=
actions.end();
media_session_action_seek_to_handled_ =
actions.find(media_session::mojom::MediaSessionAction::kSeekTo) !=
actions.end();
if (!window_)
return;
@ -420,6 +454,10 @@ void VideoPictureInPictureWindowControllerImpl::MediaSessionPositionChanged(
const std::optional<media_session::MediaPosition>& media_position) {
media_position_ = media_position;
UpdatePlaybackState();
if (window_ && media_position.has_value()) {
window_->SetMediaPosition(*media_position);
}
}
gfx::Size VideoPictureInPictureWindowControllerImpl::GetSize() {

@ -72,6 +72,8 @@ class CONTENT_EXPORT VideoPictureInPictureWindowControllerImpl
WebContents* GetWebContents() override;
WebContents* GetChildWebContents() override;
bool TogglePlayPause() override;
void Play() override;
void Pause() override;
void SkipAd() override;
void NextTrack() override;
void PreviousTrack() override;
@ -80,6 +82,7 @@ class CONTENT_EXPORT VideoPictureInPictureWindowControllerImpl
void HangUp() override;
void PreviousSlide() override;
void NextSlide() override;
void SeekTo(base::TimeDelta time) override;
void SetOnWindowCreatedNotifyObserversCallback(
base::OnceClosure on_window_created_notify_observers_callback) override;
@ -168,6 +171,12 @@ class CONTENT_EXPORT VideoPictureInPictureWindowControllerImpl
// Returns the web_contents() as a WebContentsImpl*.
WebContentsImpl* GetWebContentsImpl();
// Returns true if the player is active after this call.
bool PlayInternal();
// Returns true if the player is active after this call.
bool PauseInternal();
std::unique_ptr<VideoOverlayWindow> window_;
viz::SurfaceId surface_id_;
@ -184,6 +193,7 @@ class CONTENT_EXPORT VideoPictureInPictureWindowControllerImpl
bool media_session_action_hang_up_handled_ = false;
bool media_session_action_previous_slide_handled_ = false;
bool media_session_action_next_slide_handled_ = false;
bool media_session_action_seek_to_handled_ = false;
// Tracks the current microphone state.
bool microphone_muted_ = false;

@ -7,6 +7,7 @@
#include <memory>
#include "services/media_session/public/cpp/media_position.h"
#include "ui/gfx/native_widget_types.h"
namespace gfx {
@ -67,6 +68,8 @@ class VideoOverlayWindow {
virtual void SetHangUpButtonVisibility(bool is_visible) = 0;
virtual void SetNextSlideButtonVisibility(bool is_visible) = 0;
virtual void SetPreviousSlideButtonVisibility(bool is_visible) = 0;
virtual void SetMediaPosition(
const media_session::MediaPosition& position) = 0;
virtual void SetSurfaceId(const viz::SurfaceId& surface_id) = 0;
};

@ -6,6 +6,7 @@
#define CONTENT_PUBLIC_BROWSER_VIDEO_PICTURE_IN_PICTURE_WINDOW_CONTROLLER_H_
#include "base/functional/callback_forward.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
#include "content/public/browser/picture_in_picture_window_controller.h"
#include "ui/gfx/geometry/rect.h"
@ -34,6 +35,12 @@ class VideoPictureInPictureWindowController
// call.
virtual bool TogglePlayPause() = 0;
// Requests the player to begin playback.
virtual void Play() = 0;
// Requests the player to suspend playback.
virtual void Pause() = 0;
// Called when the user interacts with the "Toggle Microphone" control.
virtual void ToggleMicrophone() = 0;
@ -49,6 +56,9 @@ class VideoPictureInPictureWindowController
// Called when the user interacts with the "Next Slide" control.
virtual void NextSlide() = 0;
// Called when the user interacts with the progress bar control.
virtual void SeekTo(base::TimeDelta time) = 0;
// Returns the source bounds of the video, in the WebContents top-level
// coordinate space, of the video before it enters picture in picture.
virtual const gfx::Rect& GetSourceBounds() const = 0;

@ -149,6 +149,7 @@ class BoundsMatchVideoSizeOverlayWindow : public VideoOverlayWindow {
void SetHangUpButtonVisibility(bool is_visible) override {}
void SetNextSlideButtonVisibility(bool is_visible) override {}
void SetPreviousSlideButtonVisibility(bool is_visible) override {}
void SetMediaPosition(const media_session::MediaPosition&) override {}
void SetSurfaceId(const viz::SurfaceId& surface_id) override {}
private:

@ -107,6 +107,7 @@ class HeadlessVideoOverlayWindow : public content::VideoOverlayWindow {
void SetHangUpButtonVisibility(bool is_visible) override {}
void SetNextSlideButtonVisibility(bool is_visible) override {}
void SetPreviousSlideButtonVisibility(bool is_visible) override {}
void SetMediaPosition(const media_session::MediaPosition&) override {}
void SetSurfaceId(const viz::SurfaceId& surface_id) override {}