Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(463)

Side by Side Diff: third_party/WebKit/Source/core/html/AutoplayUmaHelper.cpp

Issue 2331893003: Reland "Record the offscreen playing duration of autoplaying muted videos" (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "core/html/AutoplayUmaHelper.h" 5 #include "core/html/AutoplayUmaHelper.h"
6 6
7 #include "core/dom/Document.h" 7 #include "core/dom/Document.h"
8 #include "core/dom/ElementVisibilityObserver.h" 8 #include "core/dom/ElementVisibilityObserver.h"
9 #include "core/events/Event.h" 9 #include "core/events/Event.h"
10 #include "core/frame/LocalDOMWindow.h" 10 #include "core/frame/LocalDOMWindow.h"
11 #include "core/frame/Settings.h" 11 #include "core/frame/Settings.h"
12 #include "core/html/HTMLMediaElement.h" 12 #include "core/html/HTMLMediaElement.h"
13 #include "platform/Histogram.h" 13 #include "platform/Histogram.h"
14 #include "wtf/CurrentTime.h"
14 15
15 namespace blink { 16 namespace blink {
16 17
17 namespace { 18 namespace {
18 19
19 void recordVideoAutoplayMutedPlayMethodBecomesVisibleUma(bool visible) 20 const int32_t maxOffscreenDurationUmaMS = 60 * 60 * 1000;
20 { 21 const int32_t offscreenDurationUmaBucketCount = 50;
21 DEFINE_STATIC_LOCAL(BooleanHistogram, histogram, ("Media.Video.Autoplay.Mute d.PlayMethod.BecomesVisible"));
22 histogram.count(visible);
23 }
24 22
25 } // namespace 23 } // namespace
26 24
27 AutoplayUmaHelper* AutoplayUmaHelper::create(HTMLMediaElement* element) 25 AutoplayUmaHelper* AutoplayUmaHelper::create(HTMLMediaElement* element)
28 { 26 {
29 return new AutoplayUmaHelper(element); 27 return new AutoplayUmaHelper(element);
30 } 28 }
31 29
32 AutoplayUmaHelper::AutoplayUmaHelper(HTMLMediaElement* element) 30 AutoplayUmaHelper::AutoplayUmaHelper(HTMLMediaElement* element)
33 : EventListener(CPPEventListenerType) 31 : EventListener(CPPEventListenerType)
34 , m_source(AutoplaySource::NumberOfSources) 32 , m_source(AutoplaySource::NumberOfSources)
35 , m_element(element) 33 , m_element(element)
36 , m_videoMutedPlayMethodVisibilityObserver(nullptr) { } 34 , m_mutedVideoPlayMethodVisibilityObserver(nullptr)
35 , m_mutedVideoAutoplayOffscreenStartTimeMS(0)
36 , m_mutedVideoAutoplayOffscreenDurationMS(0)
37 , m_isVisible(false)
38 , m_mutedVideoOffscreenDurationVisibilityObserver(nullptr) { }
37 39
38 AutoplayUmaHelper::~AutoplayUmaHelper() = default; 40 AutoplayUmaHelper::~AutoplayUmaHelper() = default;
39 41
40 bool AutoplayUmaHelper::operator==(const EventListener& other) const 42 bool AutoplayUmaHelper::operator==(const EventListener& other) const
41 { 43 {
42 return this == &other; 44 return this == &other;
43 } 45 }
44 46
45 void AutoplayUmaHelper::onAutoplayInitiated(AutoplaySource source) 47 void AutoplayUmaHelper::onAutoplayInitiated(AutoplaySource source)
46 { 48 {
47 DEFINE_STATIC_LOCAL(EnumerationHistogram, videoHistogram, ("Media.Video.Auto play", static_cast<int>(AutoplaySource::NumberOfSources))); 49 DEFINE_STATIC_LOCAL(EnumerationHistogram, videoHistogram, ("Media.Video.Auto play", static_cast<int>(AutoplaySource::NumberOfSources)));
48 DEFINE_STATIC_LOCAL(EnumerationHistogram, mutedVideoHistogram, ("Media.Video .Autoplay.Muted", static_cast<int>(AutoplaySource::NumberOfSources))); 50 DEFINE_STATIC_LOCAL(EnumerationHistogram, mutedVideoHistogram, ("Media.Video .Autoplay.Muted", static_cast<int>(AutoplaySource::NumberOfSources)));
49 DEFINE_STATIC_LOCAL(EnumerationHistogram, audioHistogram, ("Media.Audio.Auto play", static_cast<int>(AutoplaySource::NumberOfSources))); 51 DEFINE_STATIC_LOCAL(EnumerationHistogram, audioHistogram, ("Media.Audio.Auto play", static_cast<int>(AutoplaySource::NumberOfSources)));
50 DEFINE_STATIC_LOCAL(EnumerationHistogram, blockedMutedVideoHistogram, ("Medi a.Video.Autoplay.Muted.Blocked", AutoplayBlockedReasonMax)); 52 DEFINE_STATIC_LOCAL(EnumerationHistogram, blockedMutedVideoHistogram, ("Medi a.Video.Autoplay.Muted.Blocked", AutoplayBlockedReasonMax));
51 53
54 // Autoplay already initiated
55 // TODO(zqzhang): how about having autoplay attribute and calling `play()` i n the script?
56 if (m_source != AutoplaySource::NumberOfSources)
57 return;
58
52 m_source = source; 59 m_source = source;
53 60
54 // Record the source. 61 // Record the source.
55 if (m_element->isHTMLVideoElement()) { 62 if (m_element->isHTMLVideoElement()) {
56 videoHistogram.count(static_cast<int>(m_source)); 63 videoHistogram.count(static_cast<int>(m_source));
57 if (m_element->muted()) 64 if (m_element->muted())
58 mutedVideoHistogram.count(static_cast<int>(m_source)); 65 mutedVideoHistogram.count(static_cast<int>(m_source));
59 } else { 66 } else {
60 audioHistogram.count(static_cast<int>(m_source)); 67 audioHistogram.count(static_cast<int>(m_source));
61 } 68 }
62 69
63 // Record if it will be blocked by Data Saver or Autoplay setting. 70 // Record if it will be blocked by Data Saver or Autoplay setting.
64 if (m_element->isHTMLVideoElement() && m_element->muted() && RuntimeEnabledF eatures::autoplayMutedVideosEnabled()) { 71 if (m_element->isHTMLVideoElement() && m_element->muted() && RuntimeEnabledF eatures::autoplayMutedVideosEnabled()) {
65 bool dataSaverEnabled = m_element->document().settings() && m_element->d ocument().settings()->dataSaverEnabled(); 72 bool dataSaverEnabled = m_element->document().settings() && m_element->d ocument().settings()->dataSaverEnabled();
66 bool blockedBySetting = !m_element->isAutoplayAllowedPerSettings(); 73 bool blockedBySetting = !m_element->isAutoplayAllowedPerSettings();
67 74
68 if (dataSaverEnabled && blockedBySetting) { 75 if (dataSaverEnabled && blockedBySetting) {
69 blockedMutedVideoHistogram.count(AutoplayBlockedReasonDataSaverAndSe tting); 76 blockedMutedVideoHistogram.count(AutoplayBlockedReasonDataSaverAndSe tting);
70 } else if (dataSaverEnabled) { 77 } else if (dataSaverEnabled) {
71 blockedMutedVideoHistogram.count(AutoplayBlockedReasonDataSaver); 78 blockedMutedVideoHistogram.count(AutoplayBlockedReasonDataSaver);
72 } else if (blockedBySetting) { 79 } else if (blockedBySetting) {
73 blockedMutedVideoHistogram.count(AutoplayBlockedReasonSetting); 80 blockedMutedVideoHistogram.count(AutoplayBlockedReasonSetting);
74 } 81 }
75 } 82 }
76 83
77 if (m_source == AutoplaySource::Method && m_element->isHTMLVideoElement() && m_element->muted()) 84 m_element->addEventListener(EventTypeNames::playing, this, false);
78 m_element->addEventListener(EventTypeNames::playing, this, false);
79 } 85 }
80 86
81 void AutoplayUmaHelper::recordAutoplayUnmuteStatus(AutoplayUnmuteActionStatus st atus) 87 void AutoplayUmaHelper::recordAutoplayUnmuteStatus(AutoplayUnmuteActionStatus st atus)
82 { 88 {
83 DEFINE_STATIC_LOCAL(EnumerationHistogram, autoplayUnmuteHistogram, ("Media.V ideo.Autoplay.Muted.UnmuteAction", static_cast<int>(AutoplayUnmuteActionStatus:: NumberOfStatus))); 89 DEFINE_STATIC_LOCAL(EnumerationHistogram, autoplayUnmuteHistogram, ("Media.V ideo.Autoplay.Muted.UnmuteAction", static_cast<int>(AutoplayUnmuteActionStatus:: NumberOfStatus)));
84 90
85 autoplayUnmuteHistogram.count(static_cast<int>(status)); 91 autoplayUnmuteHistogram.count(static_cast<int>(status));
86 } 92 }
87 93
88 void AutoplayUmaHelper::didMoveToNewDocument(Document& oldDocument) 94 void AutoplayUmaHelper::didMoveToNewDocument(Document& oldDocument)
89 { 95 {
90 if (!m_videoMutedPlayMethodVisibilityObserver) 96 if (!shouldListenToUnloadEvent())
91 return; 97 return;
92 98
93 if (oldDocument.domWindow()) 99 if (oldDocument.domWindow())
94 oldDocument.domWindow()->removeEventListener(EventTypeNames::unload, thi s, false); 100 oldDocument.domWindow()->removeEventListener(EventTypeNames::unload, thi s, false);
95 if (m_element && m_element->document().domWindow()) 101 if (m_element && m_element->document().domWindow())
96 m_element->document().domWindow()->addEventListener(EventTypeNames::unlo ad, this, false); 102 m_element->document().domWindow()->addEventListener(EventTypeNames::unlo ad, this, false);
97 } 103 }
98 104
99 void AutoplayUmaHelper::onVisibilityChangedForVideoMutedPlayMethod(bool isVisibl e) 105 void AutoplayUmaHelper::onVisibilityChangedForMutedVideoPlayMethodBecomeVisible( bool isVisible)
100 { 106 {
101 if (!isVisible || !m_videoMutedPlayMethodVisibilityObserver) 107 if (!isVisible || !m_mutedVideoPlayMethodVisibilityObserver)
102 return; 108 return;
103 109
104 recordVideoAutoplayMutedPlayMethodBecomesVisibleUma(true); 110 maybeStopRecordingMutedVideoPlayMethodBecomeVisible(true);
105 m_videoMutedPlayMethodVisibilityObserver->stop(); 111 }
106 m_videoMutedPlayMethodVisibilityObserver = nullptr; 112
107 if (m_element && m_element->document().domWindow()) 113 void AutoplayUmaHelper::onVisibilityChangedForMutedVideoOffscreenDuration(bool i sVisible)
108 m_element->document().domWindow()->removeEventListener(EventTypeNames::u nload, this, false); 114 {
115 if (isVisible == m_isVisible)
116 return;
117
118 if (isVisible)
119 m_mutedVideoAutoplayOffscreenDurationMS += static_cast<int64_t>(monotoni callyIncreasingTimeMS()) - m_mutedVideoAutoplayOffscreenStartTimeMS;
120 else
121 m_mutedVideoAutoplayOffscreenStartTimeMS = static_cast<int64_t>(monotoni callyIncreasingTimeMS());
122
123 m_isVisible = isVisible;
109 } 124 }
110 125
111 void AutoplayUmaHelper::handleEvent(ExecutionContext* executionContext, Event* e vent) 126 void AutoplayUmaHelper::handleEvent(ExecutionContext* executionContext, Event* e vent)
112 { 127 {
113 if (event->type() == EventTypeNames::playing) 128 if (event->type() == EventTypeNames::playing)
114 handlePlayingEvent(); 129 handlePlayingEvent();
130 else if (event->type() == EventTypeNames::pause)
131 handlePauseEvent();
115 else if (event->type() == EventTypeNames::unload) 132 else if (event->type() == EventTypeNames::unload)
116 handleUnloadEvent(); 133 handleUnloadEvent();
117 else 134 else
118 NOTREACHED(); 135 NOTREACHED();
119 } 136 }
120 137
138 void AutoplayUmaHelper::handlePlayingEvent()
139 {
140 maybeStartRecordingMutedVideoPlayMethodBecomeVisible();
141 maybeStartRecordingMutedVideoOffscreenDuration();
142
143 m_element->removeEventListener(EventTypeNames::playing, this, false);
144 }
145
146 void AutoplayUmaHelper::handlePauseEvent()
147 {
148 maybeStopRecordingMutedVideoOffscreenDuration();
149 }
150
121 void AutoplayUmaHelper::handleUnloadEvent() 151 void AutoplayUmaHelper::handleUnloadEvent()
122 { 152 {
123 if (m_videoMutedPlayMethodVisibilityObserver) { 153 maybeStopRecordingMutedVideoPlayMethodBecomeVisible(false);
124 recordVideoAutoplayMutedPlayMethodBecomesVisibleUma(false); 154 maybeStopRecordingMutedVideoOffscreenDuration();
125 m_videoMutedPlayMethodVisibilityObserver->stop();
126 m_videoMutedPlayMethodVisibilityObserver = nullptr;
127 if (m_element && m_element->document().domWindow())
128 m_element->document().domWindow()->removeEventListener(EventTypeName s::unload, this, false);
129 }
130 } 155 }
131 156
132 void AutoplayUmaHelper::handlePlayingEvent() 157 void AutoplayUmaHelper::maybeStartRecordingMutedVideoPlayMethodBecomeVisible()
133 { 158 {
134 if (m_source == AutoplaySource::Method && m_element->isHTMLVideoElement() && m_element->muted()) { 159 if (m_source != AutoplaySource::Method || !m_element->isHTMLVideoElement() | | !m_element->muted())
135 if (!m_videoMutedPlayMethodVisibilityObserver) { 160 return;
136 m_videoMutedPlayMethodVisibilityObserver = new ElementVisibilityObse rver(m_element, WTF::bind(&AutoplayUmaHelper::onVisibilityChangedForVideoMutedPl ayMethod, wrapWeakPersistent(this))); 161
137 m_videoMutedPlayMethodVisibilityObserver->start(); 162 m_mutedVideoPlayMethodVisibilityObserver = new ElementVisibilityObserver(m_e lement, WTF::bind(&AutoplayUmaHelper::onVisibilityChangedForMutedVideoPlayMethod BecomeVisible, wrapWeakPersistent(this)));
138 if (m_element && m_element->document().domWindow()) 163 m_mutedVideoPlayMethodVisibilityObserver->start();
139 m_element->document().domWindow()->addEventListener(EventTypeNam es::unload, this, false); 164 if (m_element->document().domWindow())
140 } 165 m_element->document().domWindow()->addEventListener(EventTypeNames::unlo ad, this, false);
166 }
167
168 void AutoplayUmaHelper::maybeStopRecordingMutedVideoPlayMethodBecomeVisible(bool visible)
169 {
170 if (!m_mutedVideoPlayMethodVisibilityObserver)
171 return;
172
173 DEFINE_STATIC_LOCAL(BooleanHistogram, histogram, ("Media.Video.Autoplay.Mute d.PlayMethod.BecomesVisible"));
174
175 histogram.count(visible);
176 m_mutedVideoPlayMethodVisibilityObserver->stop();
177 m_mutedVideoPlayMethodVisibilityObserver = nullptr;
178 maybeUnregisterUnloadListener();
179 }
180
181 void AutoplayUmaHelper::maybeStartRecordingMutedVideoOffscreenDuration()
182 {
183 if (!m_element->isHTMLVideoElement() || !m_element->muted())
184 return;
185
186 // Start recording muted video playing offscreen duration.
187 m_mutedVideoAutoplayOffscreenStartTimeMS = static_cast<int64_t>(monotonicall yIncreasingTimeMS());
188 m_isVisible = false;
189 m_mutedVideoOffscreenDurationVisibilityObserver = new ElementVisibilityObser ver(m_element, WTF::bind(&AutoplayUmaHelper::onVisibilityChangedForMutedVideoOff screenDuration, wrapWeakPersistent(this)));
190 m_mutedVideoOffscreenDurationVisibilityObserver->start();
191 m_element->addEventListener(EventTypeNames::pause, this, false);
192 if (m_element->document().domWindow())
193 m_element->document().domWindow()->addEventListener(EventTypeNames::unlo ad, this, false);
194 }
195
196 void AutoplayUmaHelper::maybeStopRecordingMutedVideoOffscreenDuration()
197 {
198 if (!m_mutedVideoOffscreenDurationVisibilityObserver)
199 return;
200
201 if (!m_isVisible)
202 m_mutedVideoAutoplayOffscreenDurationMS += static_cast<int64_t>(monotoni callyIncreasingTimeMS()) - m_mutedVideoAutoplayOffscreenStartTimeMS;
203
204 // Since histograms uses int32_t, the duration needs to be limited to std::n umeric_limits<int32_t>::max().
205 int32_t boundedTime = static_cast<int32_t>(std::min<int64_t>(m_mutedVideoAut oplayOffscreenDurationMS, std::numeric_limits<int32_t>::max()));
206
207 if (m_source == AutoplaySource::Attribute) {
208 DEFINE_STATIC_LOCAL(CustomCountHistogram, durationHistogram, ("Media.Vid eo.Autoplay.Muted.Attribute.OffscreenDuration", 1, maxOffscreenDurationUmaMS, of fscreenDurationUmaBucketCount));
209 durationHistogram.count(boundedTime);
210 } else {
211 DEFINE_STATIC_LOCAL(CustomCountHistogram, durationHistogram, ("Media.Vid eo.Autoplay.Muted.PlayMethod.OffscreenDuration", 1, maxOffscreenDurationUmaMS, o ffscreenDurationUmaBucketCount));
212 durationHistogram.count(boundedTime);
141 } 213 }
142 m_element->removeEventListener(EventTypeNames::playing, this, false); 214 m_mutedVideoOffscreenDurationVisibilityObserver->stop();
215 m_mutedVideoOffscreenDurationVisibilityObserver = nullptr;
216 m_mutedVideoAutoplayOffscreenDurationMS = 0;
217 m_element->removeEventListener(EventTypeNames::pause, this, false);
218 maybeUnregisterUnloadListener();
219 }
220
221 void AutoplayUmaHelper::maybeUnregisterUnloadListener()
222 {
223 if (!shouldListenToUnloadEvent() && m_element && m_element->document().domWi ndow())
224 m_element->document().domWindow()->removeEventListener(EventTypeNames::u nload, this, false);
225 }
226
227 bool AutoplayUmaHelper::shouldListenToUnloadEvent() const
228 {
229 return m_mutedVideoPlayMethodVisibilityObserver || m_mutedVideoOffscreenDura tionVisibilityObserver;
143 } 230 }
144 231
145 DEFINE_TRACE(AutoplayUmaHelper) 232 DEFINE_TRACE(AutoplayUmaHelper)
146 { 233 {
147 EventListener::trace(visitor); 234 EventListener::trace(visitor);
148 visitor->trace(m_element); 235 visitor->trace(m_element);
149 visitor->trace(m_videoMutedPlayMethodVisibilityObserver); 236 visitor->trace(m_mutedVideoPlayMethodVisibilityObserver);
237 visitor->trace(m_mutedVideoOffscreenDurationVisibilityObserver);
150 } 238 }
151 239
152 } // namespace blink 240 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/html/AutoplayUmaHelper.h ('k') | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698