OLD | NEW |
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/Settings.h" | 10 #include "core/frame/Settings.h" |
(...skipping 11 matching lines...) Expand all Loading... |
22 | 22 |
23 } // namespace | 23 } // namespace |
24 | 24 |
25 AutoplayUmaHelper* AutoplayUmaHelper::create(HTMLMediaElement* element) { | 25 AutoplayUmaHelper* AutoplayUmaHelper::create(HTMLMediaElement* element) { |
26 return new AutoplayUmaHelper(element); | 26 return new AutoplayUmaHelper(element); |
27 } | 27 } |
28 | 28 |
29 AutoplayUmaHelper::AutoplayUmaHelper(HTMLMediaElement* element) | 29 AutoplayUmaHelper::AutoplayUmaHelper(HTMLMediaElement* element) |
30 : EventListener(CPPEventListenerType), | 30 : EventListener(CPPEventListenerType), |
31 ContextLifecycleObserver(nullptr), | 31 ContextLifecycleObserver(nullptr), |
32 m_source(AutoplaySource::NumberOfSources), | |
33 m_element(element), | 32 m_element(element), |
34 m_mutedVideoPlayMethodVisibilityObserver(nullptr), | 33 m_mutedVideoPlayMethodVisibilityObserver(nullptr), |
35 m_mutedVideoAutoplayOffscreenStartTimeMS(0), | 34 m_mutedVideoAutoplayOffscreenStartTimeMS(0), |
36 m_mutedVideoAutoplayOffscreenDurationMS(0), | 35 m_mutedVideoAutoplayOffscreenDurationMS(0), |
37 m_isVisible(false), | 36 m_isVisible(false), |
38 m_mutedVideoOffscreenDurationVisibilityObserver(nullptr) {} | 37 m_mutedVideoOffscreenDurationVisibilityObserver(nullptr) {} |
39 | 38 |
40 AutoplayUmaHelper::~AutoplayUmaHelper() = default; | 39 AutoplayUmaHelper::~AutoplayUmaHelper() = default; |
41 | 40 |
42 bool AutoplayUmaHelper::operator==(const EventListener& other) const { | 41 bool AutoplayUmaHelper::operator==(const EventListener& other) const { |
43 return this == &other; | 42 return this == &other; |
44 } | 43 } |
45 | 44 |
46 void AutoplayUmaHelper::onAutoplayInitiated(AutoplaySource source) { | 45 void AutoplayUmaHelper::onAutoplayInitiated(AutoplaySource source) { |
47 DEFINE_STATIC_LOCAL(EnumerationHistogram, videoHistogram, | 46 DEFINE_STATIC_LOCAL(EnumerationHistogram, videoHistogram, |
48 ("Media.Video.Autoplay", | 47 ("Media.Video.Autoplay", |
49 static_cast<int>(AutoplaySource::NumberOfSources))); | 48 static_cast<int>(AutoplaySource::NumberOfUmaSources))); |
50 DEFINE_STATIC_LOCAL(EnumerationHistogram, mutedVideoHistogram, | 49 DEFINE_STATIC_LOCAL(EnumerationHistogram, mutedVideoHistogram, |
51 ("Media.Video.Autoplay.Muted", | 50 ("Media.Video.Autoplay.Muted", |
52 static_cast<int>(AutoplaySource::NumberOfSources))); | 51 static_cast<int>(AutoplaySource::NumberOfUmaSources))); |
53 DEFINE_STATIC_LOCAL(EnumerationHistogram, audioHistogram, | 52 DEFINE_STATIC_LOCAL(EnumerationHistogram, audioHistogram, |
54 ("Media.Audio.Autoplay", | 53 ("Media.Audio.Autoplay", |
55 static_cast<int>(AutoplaySource::NumberOfSources))); | 54 static_cast<int>(AutoplaySource::NumberOfUmaSources))); |
56 DEFINE_STATIC_LOCAL( | 55 DEFINE_STATIC_LOCAL( |
57 EnumerationHistogram, blockedMutedVideoHistogram, | 56 EnumerationHistogram, blockedMutedVideoHistogram, |
58 ("Media.Video.Autoplay.Muted.Blocked", AutoplayBlockedReasonMax)); | 57 ("Media.Video.Autoplay.Muted.Blocked", AutoplayBlockedReasonMax)); |
59 | 58 |
60 // Autoplay already initiated | 59 // Autoplay already initiated |
61 // TODO(zqzhang): how about having autoplay attribute and calling `play()` in | 60 if (m_sources.count(source)) |
62 // the script? | |
63 if (hasSource()) | |
64 return; | 61 return; |
65 | 62 |
66 m_source = source; | 63 m_sources.insert(source); |
67 | 64 |
68 // Record the source. | 65 // Record the source. |
69 if (m_element->isHTMLVideoElement()) { | 66 if (m_element->isHTMLVideoElement()) { |
70 videoHistogram.count(static_cast<int>(m_source)); | 67 videoHistogram.count(static_cast<int>(source)); |
71 if (m_element->muted()) | 68 if (m_element->muted()) |
72 mutedVideoHistogram.count(static_cast<int>(m_source)); | 69 mutedVideoHistogram.count(static_cast<int>(source)); |
73 } else { | 70 } else { |
74 audioHistogram.count(static_cast<int>(m_source)); | 71 audioHistogram.count(static_cast<int>(source)); |
| 72 } |
| 73 |
| 74 // Record dual source. |
| 75 if (m_sources.size() == |
| 76 static_cast<size_t>(AutoplaySource::NumberOfSources)) { |
| 77 if (m_element->isHTMLVideoElement()) { |
| 78 videoHistogram.count(static_cast<int>(AutoplaySource::DualSource)); |
| 79 if (m_element->muted()) |
| 80 mutedVideoHistogram.count(static_cast<int>(AutoplaySource::DualSource)); |
| 81 } else { |
| 82 audioHistogram.count(static_cast<int>(AutoplaySource::DualSource)); |
| 83 } |
75 } | 84 } |
76 | 85 |
77 // Record the child frame and top-level frame URLs for autoplay muted videos | 86 // Record the child frame and top-level frame URLs for autoplay muted videos |
78 // by attribute. | 87 // by attribute. |
79 if (m_element->isHTMLVideoElement() && m_element->muted()) { | 88 if (m_element->isHTMLVideoElement() && m_element->muted()) { |
80 if (source == AutoplaySource::Attribute) { | 89 if (m_sources.size() == |
| 90 static_cast<size_t>(AutoplaySource::NumberOfSources)) { |
| 91 Platform::current()->recordRapporURL( |
| 92 "Media.Video.Autoplay.Muted.DualSource.Frame", |
| 93 m_element->document().url()); |
| 94 } else if (source == AutoplaySource::Attribute) { |
81 Platform::current()->recordRapporURL( | 95 Platform::current()->recordRapporURL( |
82 "Media.Video.Autoplay.Muted.Attribute.Frame", | 96 "Media.Video.Autoplay.Muted.Attribute.Frame", |
83 m_element->document().url()); | 97 m_element->document().url()); |
84 } else { | 98 } else { |
85 DCHECK(source == AutoplaySource::Method); | 99 DCHECK(source == AutoplaySource::Method); |
86 Platform::current()->recordRapporURL( | 100 Platform::current()->recordRapporURL( |
87 "Media.Video.Autoplay.Muted.PlayMethod.Frame", | 101 "Media.Video.Autoplay.Muted.PlayMethod.Frame", |
88 m_element->document().url()); | 102 m_element->document().url()); |
89 } | 103 } |
90 } | 104 } |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
254 void AutoplayUmaHelper::contextDestroyed(ExecutionContext*) { | 268 void AutoplayUmaHelper::contextDestroyed(ExecutionContext*) { |
255 handleContextDestroyed(); | 269 handleContextDestroyed(); |
256 } | 270 } |
257 | 271 |
258 void AutoplayUmaHelper::handleContextDestroyed() { | 272 void AutoplayUmaHelper::handleContextDestroyed() { |
259 maybeStopRecordingMutedVideoPlayMethodBecomeVisible(false); | 273 maybeStopRecordingMutedVideoPlayMethodBecomeVisible(false); |
260 maybeStopRecordingMutedVideoOffscreenDuration(); | 274 maybeStopRecordingMutedVideoOffscreenDuration(); |
261 } | 275 } |
262 | 276 |
263 void AutoplayUmaHelper::maybeStartRecordingMutedVideoPlayMethodBecomeVisible() { | 277 void AutoplayUmaHelper::maybeStartRecordingMutedVideoPlayMethodBecomeVisible() { |
264 if (m_source != AutoplaySource::Method || !m_element->isHTMLVideoElement() || | 278 if (!m_sources.count(AutoplaySource::Method) || |
265 !m_element->muted()) | 279 !m_element->isHTMLVideoElement() || !m_element->muted()) |
266 return; | 280 return; |
267 | 281 |
268 m_mutedVideoPlayMethodVisibilityObserver = new ElementVisibilityObserver( | 282 m_mutedVideoPlayMethodVisibilityObserver = new ElementVisibilityObserver( |
269 m_element, | 283 m_element, |
270 WTF::bind(&AutoplayUmaHelper:: | 284 WTF::bind(&AutoplayUmaHelper:: |
271 onVisibilityChangedForMutedVideoPlayMethodBecomeVisible, | 285 onVisibilityChangedForMutedVideoPlayMethodBecomeVisible, |
272 wrapWeakPersistent(this))); | 286 wrapWeakPersistent(this))); |
273 m_mutedVideoPlayMethodVisibilityObserver->start(); | 287 m_mutedVideoPlayMethodVisibilityObserver->start(); |
274 setContext(&m_element->document()); | 288 setContext(&m_element->document()); |
275 } | 289 } |
276 | 290 |
277 void AutoplayUmaHelper::maybeStopRecordingMutedVideoPlayMethodBecomeVisible( | 291 void AutoplayUmaHelper::maybeStopRecordingMutedVideoPlayMethodBecomeVisible( |
278 bool visible) { | 292 bool visible) { |
279 if (!m_mutedVideoPlayMethodVisibilityObserver) | 293 if (!m_mutedVideoPlayMethodVisibilityObserver) |
280 return; | 294 return; |
281 | 295 |
282 DEFINE_STATIC_LOCAL(BooleanHistogram, histogram, | 296 DEFINE_STATIC_LOCAL(BooleanHistogram, histogram, |
283 ("Media.Video.Autoplay.Muted.PlayMethod.BecomesVisible")); | 297 ("Media.Video.Autoplay.Muted.PlayMethod.BecomesVisible")); |
284 | 298 |
285 histogram.count(visible); | 299 histogram.count(visible); |
286 m_mutedVideoPlayMethodVisibilityObserver->stop(); | 300 m_mutedVideoPlayMethodVisibilityObserver->stop(); |
287 m_mutedVideoPlayMethodVisibilityObserver = nullptr; | 301 m_mutedVideoPlayMethodVisibilityObserver = nullptr; |
288 maybeUnregisterContextDestroyedObserver(); | 302 maybeUnregisterContextDestroyedObserver(); |
289 } | 303 } |
290 | 304 |
291 void AutoplayUmaHelper::maybeStartRecordingMutedVideoOffscreenDuration() { | 305 void AutoplayUmaHelper::maybeStartRecordingMutedVideoOffscreenDuration() { |
292 if (!m_element->isHTMLVideoElement() || !m_element->muted()) | 306 if (!m_element->isHTMLVideoElement() || !m_element->muted() || |
| 307 !m_sources.count(AutoplaySource::Method)) |
293 return; | 308 return; |
294 | 309 |
295 // Start recording muted video playing offscreen duration. | 310 // Start recording muted video playing offscreen duration. |
296 m_mutedVideoAutoplayOffscreenStartTimeMS = | 311 m_mutedVideoAutoplayOffscreenStartTimeMS = |
297 static_cast<int64_t>(monotonicallyIncreasingTimeMS()); | 312 static_cast<int64_t>(monotonicallyIncreasingTimeMS()); |
298 m_isVisible = false; | 313 m_isVisible = false; |
299 m_mutedVideoOffscreenDurationVisibilityObserver = | 314 m_mutedVideoOffscreenDurationVisibilityObserver = |
300 new ElementVisibilityObserver( | 315 new ElementVisibilityObserver( |
301 m_element, | 316 m_element, |
302 WTF::bind(&AutoplayUmaHelper:: | 317 WTF::bind(&AutoplayUmaHelper:: |
(...skipping 12 matching lines...) Expand all Loading... |
315 m_mutedVideoAutoplayOffscreenDurationMS += | 330 m_mutedVideoAutoplayOffscreenDurationMS += |
316 static_cast<int64_t>(monotonicallyIncreasingTimeMS()) - | 331 static_cast<int64_t>(monotonicallyIncreasingTimeMS()) - |
317 m_mutedVideoAutoplayOffscreenStartTimeMS; | 332 m_mutedVideoAutoplayOffscreenStartTimeMS; |
318 | 333 |
319 // Since histograms uses int32_t, the duration needs to be limited to | 334 // Since histograms uses int32_t, the duration needs to be limited to |
320 // std::numeric_limits<int32_t>::max(). | 335 // std::numeric_limits<int32_t>::max(). |
321 int32_t boundedTime = static_cast<int32_t>( | 336 int32_t boundedTime = static_cast<int32_t>( |
322 std::min<int64_t>(m_mutedVideoAutoplayOffscreenDurationMS, | 337 std::min<int64_t>(m_mutedVideoAutoplayOffscreenDurationMS, |
323 std::numeric_limits<int32_t>::max())); | 338 std::numeric_limits<int32_t>::max())); |
324 | 339 |
325 if (m_source == AutoplaySource::Method) { | 340 DCHECK(m_sources.count(AutoplaySource::Method)); |
326 DEFINE_STATIC_LOCAL( | 341 |
327 CustomCountHistogram, durationHistogram, | 342 DEFINE_STATIC_LOCAL( |
328 ("Media.Video.Autoplay.Muted.PlayMethod.OffscreenDuration", 1, | 343 CustomCountHistogram, durationHistogram, |
329 maxOffscreenDurationUmaMS, offscreenDurationUmaBucketCount)); | 344 ("Media.Video.Autoplay.Muted.PlayMethod.OffscreenDuration", 1, |
330 durationHistogram.count(boundedTime); | 345 maxOffscreenDurationUmaMS, offscreenDurationUmaBucketCount)); |
331 } | 346 durationHistogram.count(boundedTime); |
| 347 |
332 m_mutedVideoOffscreenDurationVisibilityObserver->stop(); | 348 m_mutedVideoOffscreenDurationVisibilityObserver->stop(); |
333 m_mutedVideoOffscreenDurationVisibilityObserver = nullptr; | 349 m_mutedVideoOffscreenDurationVisibilityObserver = nullptr; |
334 m_mutedVideoAutoplayOffscreenDurationMS = 0; | 350 m_mutedVideoAutoplayOffscreenDurationMS = 0; |
335 maybeUnregisterMediaElementPauseListener(); | 351 maybeUnregisterMediaElementPauseListener(); |
336 maybeUnregisterContextDestroyedObserver(); | 352 maybeUnregisterContextDestroyedObserver(); |
337 } | 353 } |
338 | 354 |
339 void AutoplayUmaHelper::maybeRecordUserPausedAutoplayingCrossOriginVideo() { | 355 void AutoplayUmaHelper::maybeRecordUserPausedAutoplayingCrossOriginVideo() { |
340 recordCrossOriginAutoplayResult(CrossOriginAutoplayResult::UserPaused); | 356 recordCrossOriginAutoplayResult(CrossOriginAutoplayResult::UserPaused); |
341 maybeUnregisterMediaElementPauseListener(); | 357 maybeUnregisterMediaElementPauseListener(); |
(...skipping 14 matching lines...) Expand all Loading... |
356 } | 372 } |
357 | 373 |
358 bool AutoplayUmaHelper::shouldListenToContextDestroyed() const { | 374 bool AutoplayUmaHelper::shouldListenToContextDestroyed() const { |
359 return m_mutedVideoPlayMethodVisibilityObserver || | 375 return m_mutedVideoPlayMethodVisibilityObserver || |
360 m_mutedVideoOffscreenDurationVisibilityObserver; | 376 m_mutedVideoOffscreenDurationVisibilityObserver; |
361 } | 377 } |
362 | 378 |
363 bool AutoplayUmaHelper::shouldRecordUserPausedAutoplayingCrossOriginVideo() | 379 bool AutoplayUmaHelper::shouldRecordUserPausedAutoplayingCrossOriginVideo() |
364 const { | 380 const { |
365 return m_element->isInCrossOriginFrame() && m_element->isHTMLVideoElement() && | 381 return m_element->isInCrossOriginFrame() && m_element->isHTMLVideoElement() && |
366 m_source != AutoplaySource::NumberOfSources && | 382 !m_sources.empty() && |
367 !m_recordedCrossOriginAutoplayResults.count( | 383 !m_recordedCrossOriginAutoplayResults.count( |
368 CrossOriginAutoplayResult::UserPaused); | 384 CrossOriginAutoplayResult::UserPaused); |
369 } | 385 } |
370 | 386 |
371 DEFINE_TRACE(AutoplayUmaHelper) { | 387 DEFINE_TRACE(AutoplayUmaHelper) { |
372 EventListener::trace(visitor); | 388 EventListener::trace(visitor); |
373 ContextLifecycleObserver::trace(visitor); | 389 ContextLifecycleObserver::trace(visitor); |
374 visitor->trace(m_element); | 390 visitor->trace(m_element); |
375 visitor->trace(m_mutedVideoPlayMethodVisibilityObserver); | 391 visitor->trace(m_mutedVideoPlayMethodVisibilityObserver); |
376 visitor->trace(m_mutedVideoOffscreenDurationVisibilityObserver); | 392 visitor->trace(m_mutedVideoOffscreenDurationVisibilityObserver); |
377 } | 393 } |
378 | 394 |
379 } // namespace blink | 395 } // namespace blink |
OLD | NEW |