summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/html/media/autoplay_uma_helper.h
blob: 5135f0f1fe6216812a7423b24e9dc60b1594fd82 (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
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
// 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/context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/dom/events/native_event_listener.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/time.h"

#include <set>

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,
  // Used for checking dual source.
  kNumberOfSources = 2,
  // Both sources are used.
  kDualSource = 2,
  // This enum value must be last.
  kNumberOfUmaSources = 3,
};

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

// These values are used for histograms. Do not reorder.
enum AutoplayBlockedReason {
  kAutoplayBlockedReasonDataSaver_DEPRECATED = 0,
  kAutoplayBlockedReasonSetting = 1,
  kAutoplayBlockedReasonDataSaverAndSetting_DEPRECATED = 2,
  // Keey at the end.
  kAutoplayBlockedReasonMax = 3
};

enum class CrossOriginAutoplayResult {
  kAutoplayAllowed = 0,
  kAutoplayBlocked = 1,
  kPlayedWithGesture = 2,
  kUserPaused = 3,
  // Keep at the end.
  kNumberOfResults = 4,
};

class Document;
class ElementVisibilityObserver;
class HTMLMediaElement;

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

 public:
  static AutoplayUmaHelper* Create(HTMLMediaElement*);

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

  void ContextDestroyed(ExecutionContext*) override;

  void OnAutoplayInitiated(AutoplaySource);

  void RecordCrossOriginAutoplayResult(CrossOriginAutoplayResult);
  void RecordAutoplayUnmuteStatus(AutoplayUnmuteActionStatus);

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

  bool IsVisible() const { return is_visible_; }

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

  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 MaybeRecordUserPausedAutoplayingCrossOriginVideo();

  void OnVisibilityChangedForMutedVideoOffscreenDuration(bool is_visibile);
  void OnVisibilityChangedForMutedVideoPlayMethodBecomeVisible(bool is_visible);

  bool ShouldListenToContextDestroyed() const;
  bool ShouldRecordUserPausedAutoplayingCrossOriginVideo() const;

  // The autoplay sources.
  std::set<AutoplaySource> sources_;

  // 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<ElementVisibilityObserver>
      muted_video_play_method_visibility_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.
  TimeTicks muted_video_autoplay_offscreen_start_time_;

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

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

  std::set<CrossOriginAutoplayResult> recorded_cross_origin_autoplay_results_;

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

  TimeTicks load_start_time_;
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_MEDIA_AUTOPLAY_UMA_HELPER_H_