| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CONTENT_RENDERER_MEDIA_RENDERER_WEBMEDIAPLAYER_DELEGATE_H_ |
| #define CONTENT_RENDERER_MEDIA_RENDERER_WEBMEDIAPLAYER_DELEGATE_H_ |
| |
| #include <map> |
| #include <memory> |
| #include <set> |
| |
| #include "base/containers/id_map.h" |
| #include "base/macros.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/single_thread_task_runner.h" |
| #include "base/time/default_tick_clock.h" |
| #include "base/timer/timer.h" |
| #include "content/common/content_export.h" |
| #include "content/public/renderer/render_frame_observer.h" |
| #include "media/blink/webmediaplayer_delegate.h" |
| |
| #if defined(OS_ANDROID) |
| #include "base/time/time.h" |
| #endif // OS_ANDROID |
| |
| namespace blink { |
| enum class WebFullscreenVideoStatus; |
| } |
| |
| namespace media { |
| |
| enum class MediaContentType; |
| |
| // Standard implementation of WebMediaPlayerDelegate; communicates state to |
| // the MediaPlayerDelegateHost. |
| class CONTENT_EXPORT RendererWebMediaPlayerDelegate |
| : public content::RenderFrameObserver, |
| public WebMediaPlayerDelegate, |
| public base::SupportsWeakPtr<RendererWebMediaPlayerDelegate> { |
| public: |
| explicit RendererWebMediaPlayerDelegate(content::RenderFrame* render_frame); |
| ~RendererWebMediaPlayerDelegate() override; |
| |
| // Returns true if this RenderFrame has ever seen media playback before. |
| bool has_played_media() const { return has_played_media_; } |
| |
| // WebMediaPlayerDelegate implementation. |
| bool IsFrameHidden() override; |
| bool IsFrameClosed() override; |
| int AddObserver(Observer* observer) override; |
| void RemoveObserver(int player_id) override; |
| void DidPlay(int player_id, |
| bool has_video, |
| bool has_audio, |
| MediaContentType media_content_type) override; |
| void DidPause(int player_id) override; |
| void PlayerGone(int player_id) override; |
| void SetIdle(int player_id, bool is_idle) override; |
| bool IsIdle(int player_id) override; |
| void ClearStaleFlag(int player_id) override; |
| bool IsStale(int player_id) override; |
| void SetIsEffectivelyFullscreen( |
| int player_id, |
| blink::WebFullscreenVideoStatus fullscreen_video_status) override; |
| void DidPlayerSizeChange(int delegate_id, const gfx::Size& size) override; |
| void DidPlayerMutedStatusChange(int delegate_id, bool muted) override; |
| void DidPictureInPictureModeStart( |
| int delegate_id, |
| const viz::SurfaceId&, |
| const gfx::Size&, |
| blink::WebMediaPlayer::PipWindowOpenedCallback) override; |
| void DidPictureInPictureModeEnd(int delegate_id, base::OnceClosure) override; |
| void DidPictureInPictureSurfaceChange(int delegate_id, |
| const viz::SurfaceId&, |
| const gfx::Size&) override; |
| void RegisterPictureInPictureWindowResizeCallback( |
| int player_id, |
| blink::WebMediaPlayer::PipWindowResizedCallback) override; |
| |
| // content::RenderFrameObserver overrides. |
| void WasHidden() override; |
| void WasShown() override; |
| bool OnMessageReceived(const IPC::Message& msg) override; |
| void OnDestruct() override; |
| |
| // Zeros out |idle_cleanup_interval_|, sets |idle_timeout_| to |idle_timeout|, |
| // and |is_jelly_bean_| to |is_jelly_bean|. A zero cleanup interval |
| // will cause the idle timer to run with each run of the message loop. |
| void SetIdleCleanupParamsForTesting(base::TimeDelta idle_timeout, |
| base::TimeDelta idle_cleanup_interval, |
| const base::TickClock* tick_clock, |
| bool is_jelly_bean); |
| bool IsIdleCleanupTimerRunningForTesting() const; |
| |
| // Note: Does not call OnFrameHidden()/OnFrameShown(). |
| void SetFrameHiddenForTesting(bool is_hidden); |
| |
| friend class RendererWebMediaPlayerDelegateTest; |
| |
| private: |
| void OnMediaDelegatePause(int player_id); |
| void OnMediaDelegatePlay(int player_id); |
| void OnMediaDelegateSeekForward(int player_id, base::TimeDelta seek_time); |
| void OnMediaDelegateSeekBackward(int player_id, base::TimeDelta seek_time); |
| void OnMediaDelegateSuspendAllMediaPlayers(); |
| void OnMediaDelegateVolumeMultiplierUpdate(int player_id, double multiplier); |
| void OnMediaDelegateBecamePersistentVideo(int player_id, bool value); |
| void OnPictureInPictureModeEnded(int player_id); |
| void OnPictureInPictureControlClicked(int player_id); |
| void OnPictureInPictureModeEndedAck(int player_id, int request_id); |
| void OnPictureInPictureModeStartedAck(int player_id, |
| int request_id, |
| const gfx::Size&); |
| void OnPictureInPictureWindowResize(int player_id, const gfx::Size&); |
| |
| // Schedules UpdateTask() to run soon. |
| void ScheduleUpdateTask(); |
| |
| // Processes state changes, dispatches CleanupIdlePlayers(). |
| void UpdateTask(); |
| |
| // Records UMAs about background playback. |
| void RecordBackgroundVideoPlayback(); |
| |
| // Runs periodically to notify stale players in |idle_player_map_| which |
| // have been idle for longer than |timeout|. |
| void CleanUpIdlePlayers(base::TimeDelta timeout); |
| |
| // True if any media has ever been played in this render frame. Affects |
| // autoplay logic in RenderFrameImpl. |
| bool has_played_media_ = false; |
| |
| bool is_frame_closed_ = false; |
| bool is_frame_hidden_for_testing_ = false; |
| |
| // State related to scheduling UpdateTask(). These are cleared each time |
| // UpdateTask() runs. |
| bool has_played_video_ = false; |
| bool pending_update_task_ = false; |
| |
| base::IDMap<Observer*> id_map_; |
| |
| // Flag for gating if players should ever transition to a stale state after a |
| // period of inactivity. |
| bool allow_idle_cleanup_ = true; |
| |
| // Tracks which players have entered an idle state. After some period of |
| // inactivity these players will be notified and become stale. |
| std::map<int, base::TimeTicks> idle_player_map_; |
| std::set<int> stale_players_; |
| base::OneShotTimer idle_cleanup_timer_; |
| |
| // Amount of time allowed to elapse after a player becomes idle before |
| // it can transition to stale. |
| base::TimeDelta idle_timeout_; |
| |
| // The polling interval used for checking the players to see if any have |
| // exceeded |idle_timeout_| since becoming idle. |
| base::TimeDelta idle_cleanup_interval_; |
| |
| // Clock used for calculating when players have become stale. May be |
| // overridden for testing. |
| const base::TickClock* tick_clock_; |
| |
| #if defined(OS_ANDROID) |
| bool was_playing_background_video_ = false; |
| |
| // Keeps track of when the background video playback started for metrics. |
| base::TimeTicks background_video_start_time_; |
| #endif // OS_ANDROID |
| |
| // The currently playing local videos. Used to determine whether |
| // OnMediaDelegatePlay() should allow the videos to play in the background or |
| // not. |
| std::set<int> playing_videos_; |
| |
| // Determined at construction time based on system information; determines |
| // when the idle cleanup timer should be fired more aggressively. |
| bool is_jelly_bean_; |
| |
| // Map associating a callback with a request sent to the browser process. The |
| // index is used as a unique request id that is passed to the browser process |
| // and will then ACK with the same id which will be used to run the right |
| // callback. |
| using ExitPictureInPictureCallbackMap = |
| base::flat_map<int, base::OnceClosure>; |
| ExitPictureInPictureCallbackMap exit_picture_in_picture_callback_map_; |
| |
| // Map associating a callback with a request sent to the browser process. The |
| // index is used as a unique request id that is passed to the browser process |
| // and will then ACK with the same id which will be used to run the right |
| // callback. |
| using EnterPictureInPictureCallbackMap = |
| base::flat_map<int, blink::WebMediaPlayer::PipWindowOpenedCallback>; |
| EnterPictureInPictureCallbackMap enter_picture_in_picture_callback_map_; |
| |
| // Counter that is used to use unique request id associated with |
| // picture-in-picture callbacks. It is incremented every time it is used. |
| int next_picture_in_picture_callback_id_ = 0; |
| |
| // Associating a player id and a Picture-in-Picture window resize callback. |
| // It holds the callback alive and guarantees that the notification sent from |
| // the browser proccess matches the player currently in Picture-in-Picture in |
| // the renderer. |
| using PictureInPictureWindowResizeObserver = |
| std::pair<int, blink::WebMediaPlayer::PipWindowResizedCallback>; |
| base::Optional<PictureInPictureWindowResizeObserver> |
| picture_in_picture_window_resize_observer_; |
| |
| DISALLOW_COPY_AND_ASSIGN(RendererWebMediaPlayerDelegate); |
| }; |
| |
| } // namespace media |
| |
| #endif // CONTENT_RENDERER_MEDIA_RENDERER_WEBMEDIAPLAYER_DELEGATE_H_ |