summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/html/media/autoplay_uma_helper.h
blob: 80c709bc43b1604bd65578056bfa59965a413839 (plain)
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
// Copyright 2016 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 THIRD_PARTY_BLINK_RENDERER_CORE_HTML_MEDIA_AUTOPLAY_UMA_HELPER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_MEDIA_AUTOPLAY_UMA_HELPER_H_

#include "third_party/blink/public/platform/web_media_player_client.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/events/native_event_listener.h"
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
#include "third_party/blink/renderer/platform/heap/handle.h"

namespace blink {

// These values are used for histograms. Do not reorder.
enum class AutoplaySource {
  // Autoplay comes from HTMLMediaElement `autoplay` attribute.
  kAttribute = 0,
  // Autoplay comes from `play()` method.
  kMethod = 1,
  // Both sources are used.
  kDualSource = 2,
  kMaxValue = kDualSource,
};

// These values are used for histograms. Do not reorder.
enum class AutoplayUnmuteActionStatus {
  kFailure = 0,
  kSuccess = 1,
  kMaxValue = kSuccess,
};

class Document;
class HTMLMediaElement;
class IntersectionObserver;
class IntersectionObserverEntry;

class CORE_EXPORT AutoplayUmaHelper : public NativeEventListener,
                                      public ExecutionContextLifecycleObserver {
  USING_GARBAGE_COLLECTED_MIXIN(AutoplayUmaHelper);

 public:
  explicit AutoplayUmaHelper(HTMLMediaElement*);
  ~AutoplayUmaHelper() override;

  void ContextDestroyed() override;

  void OnAutoplayInitiated(AutoplaySource);

  void RecordAutoplayUnmuteStatus(AutoplayUnmuteActionStatus);

  void VideoWillBeDrawnToCanvas();
  void DidMoveToNewDocument(Document& old_document);

  bool IsVisible() const { return is_visible_; }

  bool HasSource() const { return !sources_.IsEmpty(); }

  void Invoke(ExecutionContext*, Event*) override;

  void Trace(Visitor*) override;

 private:
  friend class MockAutoplayUmaHelper;

  // Called when source is initialized and loading starts.
  void OnLoadStarted();

  void HandlePlayingEvent();
  void HandlePauseEvent();
  virtual void HandleContextDestroyed();  // Make virtual for testing.

  void MaybeUnregisterContextDestroyedObserver();
  void MaybeUnregisterMediaElementPauseListener();

  void MaybeStartRecordingMutedVideoPlayMethodBecomeVisible();
  void MaybeStopRecordingMutedVideoPlayMethodBecomeVisible(bool is_visible);

  void MaybeStartRecordingMutedVideoOffscreenDuration();
  void MaybeStopRecordingMutedVideoOffscreenDuration();

  void OnIntersectionChangedForMutedVideoOffscreenDuration(
      const HeapVector<Member<IntersectionObserverEntry>>& entries);
  void OnIntersectionChangedForMutedVideoPlayMethodBecomeVisible(
      const HeapVector<Member<IntersectionObserverEntry>>& entries);

  bool ShouldListenToContextDestroyed() const;

  // The autoplay sources.
  HashSet<AutoplaySource> sources_;

  // |sources_| can be either contain 0, 1, or 2 distinct values. When
  // |sources_.size() == 2|, that indicates there are dual sources responsible
  // for autoplay.
  static constexpr size_t kDualSourceSize = 2;

  // The media element this UMA helper is attached to. |element| owns |this|.
  Member<HTMLMediaElement> element_;

  // The observer is used to observe whether a muted video autoplaying by play()
  // method become visible at some point.
  // The UMA is pending for recording as long as this observer is non-null.
  Member<IntersectionObserver> muted_video_play_method_intersection_observer_;

  // -----------------------------------------------------------------------
  // Variables used for recording the duration of autoplay muted video playing
  // offscreen.  The variables are valid when
  // |autoplayOffscrenVisibilityObserver| is non-null.
  // The recording stops whenever the playback pauses or the page is unloaded.

  // The starting time of autoplaying muted video.
  base::TimeTicks muted_video_autoplay_offscreen_start_time_;

  // The duration an autoplaying muted video has been in offscreen.
  base::TimeDelta muted_video_autoplay_offscreen_duration_;

  // Whether an autoplaying muted video is visible.
  bool is_visible_;

  // The observer is used to observer an autoplaying muted video changing it's
  // visibility, which is used for offscreen duration UMA.  The UMA is pending
  // for recording as long as this observer is non-null.
  Member<IntersectionObserver>
      muted_video_offscreen_duration_intersection_observer_;
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_MEDIA_AUTOPLAY_UMA_HELPER_H_