[go: nahoru, domu]

blob: 6f7bc695c3dc57cc0280f4cbb77bc5a98325665c [file] [log] [blame]
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_PICTURE_IN_PICTURE_VIDEO_PICTURE_IN_PICTURE_WINDOW_CONTROLLER_IMPL_H_
#define CONTENT_BROWSER_PICTURE_IN_PICTURE_VIDEO_PICTURE_IN_PICTURE_WINDOW_CONTROLLER_IMPL_H_
#include <map>
#include <set>
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "content/common/content_export.h"
#include "content/public/browser/media_player_id.h"
#include "content/public/browser/video_picture_in_picture_window_controller.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
#include "media/mojo/mojom/media_player.mojom.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/media_session/public/mojom/media_session.mojom.h"
#include "third_party/blink/public/mojom/picture_in_picture/picture_in_picture.mojom.h"
namespace content {
class PictureInPictureServiceImpl;
class PictureInPictureSession;
class WebContents;
class WebContentsImpl;
enum class PictureInPictureResult;
// VideoPictureInPictureWindowControllerImpl is the corner stone of the video
// Picture-in-Picture feature in the //content layer. It handles the session
// creation requests (sent by the PictureInPictureServiceImpl), owns the session
// object and therefore handles its lifetime, and communicate with the rest of
// the browser. Requests to the WebContents are sent by the controller and it
// gets notified when the browser needs it to update the Picture-in-Picture
// session.
// The VideoPictureInPictureWindowControllerImpl is managing Picture-in-Picture
// at a WebContents level. If multiple calls request a Picture-in-Picture
// session either in the same frame or in different frames, the controller will
// handle creating the new session, stopping the current one and making sure the
// window is kept around when possible.
class CONTENT_EXPORT VideoPictureInPictureWindowControllerImpl
: public VideoPictureInPictureWindowController,
public WebContentsUserData<VideoPictureInPictureWindowControllerImpl>,
public WebContentsObserver {
public:
// Gets a reference to the controller associated with |web_contents| and
// creates one if it does not exist. The returned pointer is guaranteed to be
// non-null.
static VideoPictureInPictureWindowControllerImpl* GetOrCreateForWebContents(
WebContents* web_contents);
VideoPictureInPictureWindowControllerImpl(
const VideoPictureInPictureWindowControllerImpl&) = delete;
VideoPictureInPictureWindowControllerImpl& operator=(
const VideoPictureInPictureWindowControllerImpl&) = delete;
~VideoPictureInPictureWindowControllerImpl() override;
using PlayerSet = std::set<int>;
// PictureInPictureWindowController:
void Show() override;
void FocusInitiator() override;
void Close(bool should_pause_video) override;
void CloseAndFocusInitiator() override;
void OnWindowDestroyed(bool should_pause_video) override;
VideoOverlayWindow* GetWindowForTesting() override;
void UpdateLayerBounds() override;
bool IsPlayerActive() override;
WebContents* GetWebContents() override;
WebContents* GetChildWebContents() override;
bool TogglePlayPause() override;
void SkipAd() override;
void NextTrack() override;
void PreviousTrack() override;
void ToggleMicrophone() override;
void ToggleCamera() override;
void HangUp() override;
void PreviousSlide() override;
void NextSlide() override;
const gfx::Rect& GetSourceBounds() const override;
std::optional<gfx::Rect> GetWindowBounds() override;
std::optional<url::Origin> GetOrigin() override;
void SetOrigin(std::optional<url::Origin> origin);
// Called by the MediaSessionImpl when the MediaSessionInfo changes.
void MediaSessionInfoChanged(
const media_session::mojom::MediaSessionInfoPtr& info);
void MediaSessionActionsChanged(
const std::set<media_session::mojom::MediaSessionAction>& actions);
void MediaSessionPositionChanged(
const std::optional<media_session::MediaPosition>& media_position);
gfx::Size GetSize();
// WebContentsObserver:
void MediaStartedPlaying(const MediaPlayerInfo&,
const MediaPlayerId&) override;
void MediaStoppedPlaying(const MediaPlayerInfo&,
const MediaPlayerId&,
WebContentsObserver::MediaStoppedReason) override;
void WebContentsDestroyed() override;
// Embeds a surface in the Picture-in-Picture window.
void EmbedSurface(const viz::SurfaceId& surface_id,
const gfx::Size& natural_size);
void SetShowPlayPauseButton(bool show_play_pause_button);
// Called by PictureInPictureServiceImpl when a session request is received.
// The call should return the |session_remote| and |window_size| as out
// params. A failure to create the session should be expressed with an empty
// |window_size| and uninitialized |session_remote|.
// Returns whether the session creation was successful.
PictureInPictureResult StartSession(
PictureInPictureServiceImpl* service,
const MediaPlayerId&,
mojo::PendingAssociatedRemote<media::mojom::MediaPlayer> player_remote,
const viz::SurfaceId& surface_id,
const gfx::Size& natural_size,
bool show_play_pause_button,
mojo::PendingRemote<blink::mojom::PictureInPictureSessionObserver>,
const gfx::Rect& source_bounds,
mojo::PendingRemote<blink::mojom::PictureInPictureSession>*
session_remote,
gfx::Size* window_size);
// Called by PictureInPictureServiceImpl when the service is about to be
// destroyed. It allows |this| to close the |active_session_| if it is
// associated with the service.
void OnServiceDeleted(PictureInPictureServiceImpl* service);
PictureInPictureSession* active_session_for_testing() const {
return active_session_.get();
}
private:
friend class WebContentsUserData<VideoPictureInPictureWindowControllerImpl>;
// Use VideoPictureInPictureWindowControllerImpl::GetOrCreateForWebContents()
// to create an instance.
explicit VideoPictureInPictureWindowControllerImpl(WebContents* web_contents);
// Recompute the playback state and update the window accordingly.
void UpdatePlaybackState();
// Signal to the media player that |this| is leaving Picture-in-Picture mode.
void OnLeavingPictureInPicture(bool should_pause_video);
// Internal method to set the states after the window was closed, whether via
// the system or by the browser.
void CloseInternal(bool should_pause_video);
// Allow play/pause button to be visible if Media Session actions "play" and
// "pause" are both handled by the website or if
// always_hide_play_pause_button_ is false.
void UpdatePlayPauseButtonVisibility();
// Returns the web_contents() as a WebContentsImpl*.
WebContentsImpl* GetWebContentsImpl();
std::unique_ptr<VideoOverlayWindow> window_;
viz::SurfaceId surface_id_;
// Used to show/hide some actions in Picture-in-Picture window. These are set
// to true when website handles some Media Session actions.
bool media_session_action_play_handled_ = false;
bool media_session_action_pause_handled_ = false;
bool media_session_action_skip_ad_handled_ = false;
bool media_session_action_next_track_handled_ = false;
bool media_session_action_previous_track_handled_ = false;
bool media_session_action_toggle_microphone_handled_ = false;
bool media_session_action_toggle_camera_handled_ = false;
bool media_session_action_hang_up_handled_ = false;
bool media_session_action_previous_slide_handled_ = false;
bool media_session_action_next_slide_handled_ = false;
// Tracks the current microphone state.
bool microphone_muted_ = false;
// Tracks the current camera state.
bool camera_turned_on_ = false;
// Used to hide play/pause button if video is a MediaStream or has infinite
// duration. Play/pause button visibility can be overridden by the Media
// Session API in UpdatePlayPauseButtonVisibility().
bool always_show_play_pause_button_ = false;
// Session currently associated with the Picture-in-Picture window. The
// session object makes the bridge with the renderer process by handling
// requests and holding states such as the active player id.
// The session will be nullptr when there is no active session.
std::unique_ptr<PictureInPictureSession> active_session_;
// The media position info as last reported to us by MediaSessionImpl.
std::optional<media_session::MediaPosition> media_position_;
// Coordinates of the video element in WebContents coordinates.
gfx::Rect source_bounds_;
// The origin of the initiator.
std::optional<url::Origin> origin_;
WEB_CONTENTS_USER_DATA_KEY_DECL();
};
} // namespace content
#endif // CONTENT_BROWSER_PICTURE_IN_PICTURE_VIDEO_PICTURE_IN_PICTURE_WINDOW_CONTROLLER_IMPL_H_