1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164

content / renderer / media / renderer_web_media_player_delegate.h [blame]

// Copyright 2015 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_RENDERER_MEDIA_RENDERER_WEB_MEDIA_PLAYER_DELEGATE_H_
#define CONTENT_RENDERER_MEDIA_RENDERER_WEB_MEDIA_PLAYER_DELEGATE_H_

#include <map>
#include <memory>
#include <set>

#include "base/containers/flat_set.h"
#include "base/containers/id_map.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/default_tick_clock.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "content/common/content_export.h"
#include "content/public/renderer/render_frame_observer.h"
#include "third_party/blink/public/platform/media/web_media_player_delegate.h"
#include "third_party/blink/public/web/web_view_observer.h"

namespace blink {
enum class WebFullscreenVideoStatus;
}

namespace media {

enum class MediaContentType;

// Standard implementation of WebMediaPlayerDelegate; communicates state to
// the MediaPlayerDelegateHost.
class CONTENT_EXPORT RendererWebMediaPlayerDelegate final
    : public content::RenderFrameObserver,
      public blink::WebViewObserver,
      public blink::WebMediaPlayerDelegate {
 public:
  explicit RendererWebMediaPlayerDelegate(content::RenderFrame* render_frame);

  RendererWebMediaPlayerDelegate(const RendererWebMediaPlayerDelegate&) =
      delete;
  RendererWebMediaPlayerDelegate& operator=(
      const RendererWebMediaPlayerDelegate&) = delete;

  ~RendererWebMediaPlayerDelegate() override;

  // Returns true if this RenderFrame has ever seen media playback before.
  bool has_played_media() const { return has_played_media_; }

  // blink::WebMediaPlayerDelegate implementation.
  bool IsPageHidden() override;
  bool IsFrameHidden() override;
  int AddObserver(Observer* observer) override;
  void RemoveObserver(int player_id) override;
  void DidMediaMetadataChange(int player_id,
                              bool has_audio,
                              bool has_video,
                              MediaContentType media_content_type) override;
  void DidPlay(int player_id) override;
  void DidPause(int player_id, bool reached_end_of_stream) 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;

  // content::RenderFrameObserver overrides.
  void OnDestruct() override;
  void OnFrameVisibilityChanged(
      blink::mojom::FrameVisibility render_status) override;

  // blink::WebViewObserver overrides.
  void OnPageVisibilityChanged(
      blink::mojom::PageVisibilityState visibility_state) override;

  // Returns the number of WebMediaPlayers that are associated with this
  // delegate.
  size_t web_media_player_count() const { return id_map_.size(); }

  // Zeros out |idle_cleanup_interval_|, sets |idle_timeout_| to |idle_timeout|,
  // and |is_low_end_| to |is_low_end|. 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_low_end);
  bool IsIdleCleanupTimerRunningForTesting() const;

  // Note: Does not call OnFrameHidden()/OnFrameShown().
  void SetFrameHiddenForTesting(bool is_frame_hidden);

  friend class RendererWebMediaPlayerDelegateTest;

 private:
  // Schedules UpdateTask() to run soon.
  void ScheduleUpdateTask();

  // Processes state changes, dispatches CleanupIdlePlayers().
  void UpdateTask();

  // 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;

  // 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.
  raw_ptr<const base::TickClock> tick_clock_;

  // Players with a video track.
  base::flat_set<int> players_with_video_;

  // The currently playing local videos. Used to determine whether
  // OnMediaDelegatePlay() should allow the videos to play in the background or
  // not.
  base::flat_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_low_end_;

  // Last page shown/hidden state sent to the player.  Unset if we have not sent
  // any message.  Used to elide duplicates.
  std::optional<bool> is_shown_;

  // Last rendered status sent to the player from the containing frame.
  bool is_frame_hidden_ = false;

  base::WeakPtrFactory<RendererWebMediaPlayerDelegate> weak_ptr_factory_{this};
};

}  // namespace media

#endif  // CONTENT_RENDERER_MEDIA_RENDERER_WEB_MEDIA_PLAYER_DELEGATE_H_