Chromium Code Reviews| Index: third_party/WebKit/Source/core/html/AutoplayUmaHelper.cpp |
| diff --git a/third_party/WebKit/Source/core/html/AutoplayUmaHelper.cpp b/third_party/WebKit/Source/core/html/AutoplayUmaHelper.cpp |
| index 0951ad198a57711fb53470157fdb8a3d86dd8859..7ba5ba6391db99d3065f475d848d9ef1a126f585 100644 |
| --- a/third_party/WebKit/Source/core/html/AutoplayUmaHelper.cpp |
| +++ b/third_party/WebKit/Source/core/html/AutoplayUmaHelper.cpp |
| @@ -10,16 +10,14 @@ |
| #include "core/frame/LocalDOMWindow.h" |
| #include "core/html/HTMLMediaElement.h" |
| #include "platform/Histogram.h" |
| +#include "wtf/CurrentTime.h" |
| namespace blink { |
| namespace { |
| -void recordVideoAutoplayMutedPlayMethodBecomesVisibleUma(bool visible) |
| -{ |
| - DEFINE_STATIC_LOCAL(BooleanHistogram, histogram, ("Media.Video.Autoplay.Muted.PlayMethod.BecomesVisible")); |
| - histogram.count(visible); |
| -} |
| +static const double maxUmaDurationMS = 1e6; |
| +static const double umaBucketCount = 20; |
| } // namespace |
| @@ -32,7 +30,11 @@ AutoplayUmaHelper::AutoplayUmaHelper(HTMLMediaElement* element) |
| : EventListener(CPPEventListenerType) |
| , m_source(AutoplaySource::NumberOfSources) |
| , m_element(element) |
| - , m_videoMutedPlayMethodVisibilityObserver(nullptr) { } |
| + , m_mutedVideoPlayMethodVisibilityObserver(nullptr) |
| + , m_mutedVideoAutoplayStartTimeMS(0) |
| + , m_mutedVideoAutoplayOffscreenDurationMS(0) |
| + , m_isVisible(false) |
| + , m_mutedVideoOffscreenDurationVisibilityObserver(nullptr) { } |
| AutoplayUmaHelper::~AutoplayUmaHelper() = default; |
| @@ -47,6 +49,11 @@ void AutoplayUmaHelper::onAutoplayInitiated(AutoplaySource source) |
| DEFINE_STATIC_LOCAL(EnumerationHistogram, mutedVideoHistogram, ("Media.Video.Autoplay.Muted", static_cast<int>(AutoplaySource::NumberOfSources))); |
| DEFINE_STATIC_LOCAL(EnumerationHistogram, audioHistogram, ("Media.Audio.Autoplay", static_cast<int>(AutoplaySource::NumberOfSources))); |
| + // Autoplay already initiated |
| + // TODO(zqzhang): how about having autoplay attribute and calling `play()` in the script? |
| + if (m_source != AutoplaySource::NumberOfSources) |
| + return; |
| + |
| m_source = source; |
| if (m_element->isHTMLVideoElement()) { |
| @@ -57,8 +64,7 @@ void AutoplayUmaHelper::onAutoplayInitiated(AutoplaySource source) |
| audioHistogram.count(static_cast<int>(m_source)); |
| } |
| - if (m_source == AutoplaySource::Method && m_element->isHTMLVideoElement() && m_element->muted()) |
| - m_element->addEventListener(EventTypeNames::playing, this, false); |
| + m_element->addEventListener(EventTypeNames::playing, this, false); |
| } |
| void AutoplayUmaHelper::recordAutoplayUnmuteStatus(AutoplayUnmuteActionStatus status) |
| @@ -70,61 +76,144 @@ void AutoplayUmaHelper::recordAutoplayUnmuteStatus(AutoplayUnmuteActionStatus st |
| void AutoplayUmaHelper::didMoveToNewDocument(Document& oldDocument) |
| { |
| - if (!m_videoMutedPlayMethodVisibilityObserver) |
| + if (!shouldListenToUnloadEvent()) |
| return; |
| oldDocument.domWindow()->removeEventListener(EventTypeNames::unload, this, false); |
| m_element->document().domWindow()->addEventListener(EventTypeNames::unload, this, false); |
| } |
| -void AutoplayUmaHelper::onVisibilityChangedForVideoMutedPlayMethod(bool isVisible) |
| +void AutoplayUmaHelper::onVisibilityChangedForMutedVideoPlayMethodBecomeVisible(bool isVisible) |
| { |
| if (!isVisible) |
| return; |
| - recordVideoAutoplayMutedPlayMethodBecomesVisibleUma(true); |
| - m_videoMutedPlayMethodVisibilityObserver->stop(); |
| - m_videoMutedPlayMethodVisibilityObserver = nullptr; |
| - m_element->document().domWindow()->removeEventListener(EventTypeNames::unload, this, false); |
| + maybeStopRecordingMutedVideoPlayMethodBecomeVisible(true); |
| +} |
| + |
| +void AutoplayUmaHelper::onVisibilityChangedForMutedVideoOffscreenDuration(bool isVisible) |
| +{ |
| + if (isVisible == m_isVisible) |
| + return; |
| + |
| + if (isVisible) |
| + m_mutedVideoAutoplayOffscreenDurationMS += monotonicallyIncreasingTimeMS() - m_mutedVideoAutoplayStartTimeMS; |
| + else |
| + m_mutedVideoAutoplayStartTimeMS = monotonicallyIncreasingTimeMS(); |
| + |
| + m_isVisible = isVisible; |
| } |
| void AutoplayUmaHelper::handleEvent(ExecutionContext* executionContext, Event* event) |
| { |
| if (event->type() == EventTypeNames::playing) |
| handlePlayingEvent(); |
| + else if (event->type() == EventTypeNames::pause) |
| + handlePauseEvent(); |
| else if (event->type() == EventTypeNames::unload) |
| handleUnloadEvent(); |
| else |
| NOTREACHED(); |
| } |
| +void AutoplayUmaHelper::handlePlayingEvent() |
| +{ |
| + maybeStartRecordingMutedVideoPlayMethodBecomeVisible(); |
| + maybeStartRecordingMutedVideoOffscreenDuration(); |
| + |
| + m_element->removeEventListener(EventTypeNames::playing, this, false); |
| +} |
| + |
| +void AutoplayUmaHelper::handlePauseEvent() |
| +{ |
| + maybeStopRecordingMutedVideoOffscreenDuration(); |
| +} |
| + |
| void AutoplayUmaHelper::handleUnloadEvent() |
| { |
| - if (m_videoMutedPlayMethodVisibilityObserver) { |
| - recordVideoAutoplayMutedPlayMethodBecomesVisibleUma(false); |
| - m_videoMutedPlayMethodVisibilityObserver->stop(); |
| - m_videoMutedPlayMethodVisibilityObserver = nullptr; |
| - m_element->document().domWindow()->removeEventListener(EventTypeNames::unload, this, false); |
| - } |
| + maybeStopRecordingMutedVideoPlayMethodBecomeVisible(false); |
| + maybeStopRecordingMutedVideoOffscreenDuration(); |
| } |
| -void AutoplayUmaHelper::handlePlayingEvent() |
| +void AutoplayUmaHelper::maybeStartRecordingMutedVideoPlayMethodBecomeVisible() |
| { |
| - if (m_source == AutoplaySource::Method && m_element->isHTMLVideoElement() && m_element->muted()) { |
| - if (!m_videoMutedPlayMethodVisibilityObserver) { |
| - m_videoMutedPlayMethodVisibilityObserver = new ElementVisibilityObserver(m_element, WTF::bind(&AutoplayUmaHelper::onVisibilityChangedForVideoMutedPlayMethod, wrapPersistent(this))); |
| - m_videoMutedPlayMethodVisibilityObserver->start(); |
| - m_element->document().domWindow()->addEventListener(EventTypeNames::unload, this, false); |
| - } |
| + if (m_source != AutoplaySource::Method || !m_element->isHTMLVideoElement() || !m_element->muted()) |
| + return; |
| + |
| + m_mutedVideoPlayMethodVisibilityObserver = new ElementVisibilityObserver(m_element, WTF::bind(&AutoplayUmaHelper::onVisibilityChangedForMutedVideoPlayMethodBecomeVisible, wrapPersistent(this))); |
| + m_mutedVideoPlayMethodVisibilityObserver->start(); |
| + m_element->document().domWindow()->addEventListener(EventTypeNames::unload, this, false); |
| +} |
| + |
| +void AutoplayUmaHelper::maybeStopRecordingMutedVideoPlayMethodBecomeVisible(bool visible) |
| +{ |
| + DEFINE_STATIC_LOCAL(BooleanHistogram, histogram, ("Media.Video.Autoplay.Muted.PlayMethod.BecomesVisible")); |
| + |
| + if (!m_mutedVideoPlayMethodVisibilityObserver) |
| + return; |
| + |
| + histogram.count(visible); |
| + m_mutedVideoPlayMethodVisibilityObserver->stop(); |
| + m_mutedVideoPlayMethodVisibilityObserver = nullptr; |
| + maybeUnregisterUnloadListener(); |
| +} |
| + |
| +void AutoplayUmaHelper::maybeStartRecordingMutedVideoOffscreenDuration() |
| +{ |
| + if (!m_element->isHTMLVideoElement() || !m_element->muted()) |
| + return; |
| + |
| + // Start recording muted video playing offscreen duration. |
| + m_mutedVideoAutoplayStartTimeMS = monotonicallyIncreasingTimeMS(); |
| + m_isVisible = false; |
| + m_mutedVideoOffscreenDurationVisibilityObserver = new ElementVisibilityObserver(m_element, WTF::bind(&AutoplayUmaHelper::onVisibilityChangedForMutedVideoOffscreenDuration, wrapPersistent(this))); |
|
mlamouri (slow - plz ping)
2016/08/17 19:27:15
wrapWeakPersistent?
Zhiqiang Zhang (Slow)
2016/08/18 10:52:43
Done.
|
| + m_mutedVideoOffscreenDurationVisibilityObserver->start(); |
| + m_element->addEventListener(EventTypeNames::pause, this, false); |
| + m_element->document().domWindow()->addEventListener(EventTypeNames::unload, this, false); |
| +} |
| + |
| +void AutoplayUmaHelper::maybeStopRecordingMutedVideoOffscreenDuration() |
| +{ |
| + if (!m_mutedVideoOffscreenDurationVisibilityObserver) |
| + return; |
| + |
| + double timeDeltaMS = m_isVisible ? m_mutedVideoAutoplayOffscreenDurationMS : maxUmaDurationMS; |
|
mlamouri (slow - plz ping)
2016/08/17 19:27:15
I'm not sure I fully understand this logic. If we
Zhiqiang Zhang (Slow)
2016/08/18 10:52:43
OK, not clamping the values now. Just found that h
|
| + if (timeDeltaMS < 0) |
| + timeDeltaMS = 0; |
| + if (timeDeltaMS > maxUmaDurationMS) |
| + timeDeltaMS = maxUmaDurationMS; |
|
mlamouri (slow - plz ping)
2016/08/17 19:27:15
I think you can use clamp():
https://cs.chromium.o
Zhiqiang Zhang (Slow)
2016/08/18 10:52:43
Not clamping the values as said in the other reply
|
| + |
| + if (m_source == AutoplaySource::Attribute) { |
| + DEFINE_STATIC_LOCAL(CustomCountHistogram, durationHistogram, ("Media.Video.Autoplay.Muted.Attribute.OffscreenDuration", 0, maxUmaDurationMS, umaBucketCount)); |
| + durationHistogram.count(timeDeltaMS); |
| + } else { |
| + DEFINE_STATIC_LOCAL(CustomCountHistogram, durationHistogram, ("Media.Video.Autoplay.Muted.PlayMethod.OffscreenDuration", 0, maxUmaDurationMS, umaBucketCount)); |
| + durationHistogram.count(timeDeltaMS); |
| } |
| - m_element->removeEventListener(EventTypeNames::playing, this, false); |
| + m_mutedVideoOffscreenDurationVisibilityObserver->stop(); |
| + m_mutedVideoOffscreenDurationVisibilityObserver = nullptr; |
| + m_mutedVideoAutoplayOffscreenDurationMS = 0; |
| + m_element->removeEventListener(EventTypeNames::pause, this, false); |
| + maybeUnregisterUnloadListener(); |
| +} |
| + |
| +void AutoplayUmaHelper::maybeUnregisterUnloadListener() |
| +{ |
| + if (!shouldListenToUnloadEvent()) |
| + m_element->document().domWindow()->removeEventListener(EventTypeNames::unload, this, false); |
| +} |
| + |
| +bool AutoplayUmaHelper::shouldListenToUnloadEvent() const |
| +{ |
| + return m_mutedVideoPlayMethodVisibilityObserver || m_mutedVideoOffscreenDurationVisibilityObserver; |
| } |
| DEFINE_TRACE(AutoplayUmaHelper) |
| { |
| EventListener::trace(visitor); |
| visitor->trace(m_element); |
| - visitor->trace(m_videoMutedPlayMethodVisibilityObserver); |
| + visitor->trace(m_mutedVideoPlayMethodVisibilityObserver); |
| + visitor->trace(m_mutedVideoOffscreenDurationVisibilityObserver); |
| } |
| } // namespace blink |