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

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

Issue 1470153004: Autoplay experiment metric fixes and additions. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: moved RecordMetricsBehavior back into HTMLMediaElement Created 4 years, 10 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 /* 1 /*
2 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved. 2 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 19 matching lines...) Expand all
30 #include "bindings/core/v8/ScriptController.h" 30 #include "bindings/core/v8/ScriptController.h"
31 #include "bindings/core/v8/ScriptEventListener.h" 31 #include "bindings/core/v8/ScriptEventListener.h"
32 #include "core/HTMLNames.h" 32 #include "core/HTMLNames.h"
33 #include "core/css/MediaList.h" 33 #include "core/css/MediaList.h"
34 #include "core/dom/Attribute.h" 34 #include "core/dom/Attribute.h"
35 #include "core/dom/ElementTraversal.h" 35 #include "core/dom/ElementTraversal.h"
36 #include "core/dom/ExceptionCode.h" 36 #include "core/dom/ExceptionCode.h"
37 #include "core/dom/Fullscreen.h" 37 #include "core/dom/Fullscreen.h"
38 #include "core/dom/shadow/ShadowRoot.h" 38 #include "core/dom/shadow/ShadowRoot.h"
39 #include "core/events/Event.h" 39 #include "core/events/Event.h"
40 #include "core/frame/FrameView.h"
40 #include "core/frame/LocalFrame.h" 41 #include "core/frame/LocalFrame.h"
41 #include "core/frame/Settings.h" 42 #include "core/frame/Settings.h"
42 #include "core/frame/UseCounter.h" 43 #include "core/frame/UseCounter.h"
43 #include "core/frame/csp/ContentSecurityPolicy.h" 44 #include "core/frame/csp/ContentSecurityPolicy.h"
44 #include "core/html/HTMLMediaSource.h" 45 #include "core/html/HTMLMediaSource.h"
45 #include "core/html/HTMLSourceElement.h" 46 #include "core/html/HTMLSourceElement.h"
46 #include "core/html/HTMLTrackElement.h" 47 #include "core/html/HTMLTrackElement.h"
47 #include "core/html/MediaError.h" 48 #include "core/html/MediaError.h"
48 #include "core/html/MediaFragmentURIParser.h" 49 #include "core/html/MediaFragmentURIParser.h"
49 #include "core/html/TimeRanges.h" 50 #include "core/html/TimeRanges.h"
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 if (contentMIMEType != "application/octet-stream" || contentTypeCodecs.isEmp ty()) { 247 if (contentMIMEType != "application/octet-stream" || contentTypeCodecs.isEmp ty()) {
247 WebMimeRegistry::SupportsType supported = Platform::current()->mimeRegis try()->supportsMediaMIMEType(contentMIMEType, contentTypeCodecs); 248 WebMimeRegistry::SupportsType supported = Platform::current()->mimeRegis try()->supportsMediaMIMEType(contentMIMEType, contentTypeCodecs);
248 return supported > WebMimeRegistry::IsNotSupported; 249 return supported > WebMimeRegistry::IsNotSupported;
249 } 250 }
250 251
251 return false; 252 return false;
252 } 253 }
253 254
254 } // anonymous namespace 255 } // anonymous namespace
255 256
257 class HTMLMediaElement::AutoplayHelperClientImpl :
sof 2016/02/25 18:55:43 Move this up into the anon namespace and declare i
liberato (no reviews please) 2016/03/14 17:09:13 can't without friending.
258 public AutoplayExperimentHelper::Client {
259
260 public:
261 static PassOwnPtrWillBeRawPtr<AutoplayHelperClientImpl> create(HTMLMediaElem ent* element)
262 {
263 return adoptPtrWillBeNoop(new AutoplayHelperClientImpl(element));
264 }
265
266 virtual ~AutoplayHelperClientImpl();
267
268 using RecordMetricsBehavior = HTMLMediaElement::RecordMetricsBehavior;
269
270 double currentTime() const override { return m_element->currentTime(); }
271 double duration() const override { return m_element->duration(); }
272 bool paused() const override { return m_element->paused(); }
273 bool muted() const override { return m_element->muted(); }
274 void setMuted(bool muted) override { m_element->setMuted(muted); }
275 void playInternal() override { m_element->playInternal(); }
276 bool isUserGestureRequiredForPlay() const override { return m_element->isUse rGestureRequiredForPlay(); }
277 void removeUserGestureRequirement() override { m_element->removeUserGestureR equirement(); }
278 void recordAutoplayMetric(AutoplayMetrics metric) override { m_element->reco rdAutoplayMetric(metric); }
279 bool shouldAutoplay() override
280 {
281 return m_element->shouldAutoplay(RecordMetricsBehavior::DoNotRecord);
282 }
283 bool isHTMLVideoElement() const override { return m_element->isHTMLVideoElem ent(); }
284 bool isHTMLAudioElement() const override { return m_element->isHTMLAudioElem ent(); }
285
286 // Document
287 bool isLegacyViewportType() override;
288 PageVisibilityState pageVisibilityState() const override;
289 String autoplayExperimentMode() const override;
290
291 // LayoutObject
292 void setRequestPositionUpdates(bool) override;
293 IntRect absoluteBoundingBoxRect() const override;
294
295 DEFINE_INLINE_VIRTUAL_TRACE() {
sof 2016/02/25 18:55:43 DEFINE_INLINE_VIRTUAL_TRACE() { ... }
liberato (no reviews please) 2016/03/14 17:09:13 Done.
296 visitor->trace(m_element);
297 Client::trace(visitor);
298 }
299
300 private:
301 AutoplayHelperClientImpl(HTMLMediaElement* element) : m_element(element) {}
302
303 RawPtrWillBeMember<HTMLMediaElement> m_element;
304 };
305
306
256 void HTMLMediaElement::recordAutoplayMetric(AutoplayMetrics metric) 307 void HTMLMediaElement::recordAutoplayMetric(AutoplayMetrics metric)
257 { 308 {
258 DEFINE_STATIC_LOCAL(EnumerationHistogram, autoplayHistogram, ("Blink.MediaEl ement.Autoplay", NumberOfAutoplayMetrics)); 309 DEFINE_STATIC_LOCAL(EnumerationHistogram, autoplayHistogram, ("Blink.MediaEl ement.Autoplay", NumberOfAutoplayMetrics));
259 autoplayHistogram.count(metric); 310 autoplayHistogram.count(metric);
260 } 311 }
261 312
262 WebMimeRegistry::SupportsType HTMLMediaElement::supportsType(const ContentType& contentType) 313 WebMimeRegistry::SupportsType HTMLMediaElement::supportsType(const ContentType& contentType)
263 { 314 {
264 DEFINE_STATIC_LOCAL(const String, codecs, ("codecs")); 315 DEFINE_STATIC_LOCAL(const String, codecs, ("codecs"));
265 316
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 , m_seeking(false) 385 , m_seeking(false)
335 , m_sentStalledEvent(false) 386 , m_sentStalledEvent(false)
336 , m_sentEndEvent(false) 387 , m_sentEndEvent(false)
337 , m_closedCaptionsVisible(false) 388 , m_closedCaptionsVisible(false)
338 , m_havePreparedToPlay(false) 389 , m_havePreparedToPlay(false)
339 , m_tracksAreReady(true) 390 , m_tracksAreReady(true)
340 , m_processingPreferenceChange(false) 391 , m_processingPreferenceChange(false)
341 , m_remoteRoutesAvailable(false) 392 , m_remoteRoutesAvailable(false)
342 , m_playingRemotely(false) 393 , m_playingRemotely(false)
343 , m_isFinalizing(false) 394 , m_isFinalizing(false)
344 , m_initialPlayWithoutUserGesture(false)
345 , m_autoplayMediaCounted(false)
346 , m_inOverlayFullscreenVideo(false) 395 , m_inOverlayFullscreenVideo(false)
347 , m_audioTracks(AudioTrackList::create(*this)) 396 , m_audioTracks(AudioTrackList::create(*this))
348 , m_videoTracks(VideoTrackList::create(*this)) 397 , m_videoTracks(VideoTrackList::create(*this))
349 , m_textTracks(nullptr) 398 , m_textTracks(nullptr)
350 , m_audioSourceNode(nullptr) 399 , m_audioSourceNode(nullptr)
351 , m_autoplayHelper(*this) 400 , m_autoplayHelperClient(AutoplayHelperClientImpl::create(this))
401 , m_autoplayHelper(AutoplayExperimentHelper::create(m_autoplayHelperClient))
352 { 402 {
353 #if ENABLE(OILPAN) 403 #if ENABLE(OILPAN)
354 ThreadState::current()->registerPreFinalizer(this); 404 ThreadState::current()->registerPreFinalizer(this);
355 #endif 405 #endif
356 ASSERT(RuntimeEnabledFeatures::mediaEnabled()); 406 ASSERT(RuntimeEnabledFeatures::mediaEnabled());
357 407
358 WTF_LOG(Media, "HTMLMediaElement::HTMLMediaElement(%p)", this); 408 WTF_LOG(Media, "HTMLMediaElement::HTMLMediaElement(%p)", this);
359 409
360 if (document.settings() && document.settings()->mediaPlaybackRequiresUserGes ture()) 410 if (document.settings() && document.settings()->mediaPlaybackRequiresUserGes ture())
361 m_userGestureRequiredForPlay = true; 411 m_userGestureRequiredForPlay = true;
362 412
363 setHasCustomStyleCallbacks(); 413 setHasCustomStyleCallbacks();
364 addElementToDocumentMap(this, &document); 414 addElementToDocumentMap(this, &document);
365 415
366 UseCounter::count(document, UseCounter::HTMLMediaElement); 416 UseCounter::count(document, UseCounter::HTMLMediaElement);
367 } 417 }
368 418
369 HTMLMediaElement::~HTMLMediaElement() 419 HTMLMediaElement::~HTMLMediaElement()
370 { 420 {
371 WTF_LOG(Media, "HTMLMediaElement::~HTMLMediaElement(%p)", this); 421 WTF_LOG(Media, "HTMLMediaElement::~HTMLMediaElement(%p)", this);
372 422
373 #if !ENABLE(OILPAN) 423 #if !ENABLE(OILPAN)
424 // Destruction of the autoplay helper requires the client, so be sure that
425 // this happens before the client is destructed.
426 if (m_autoplayHelper)
427 m_autoplayHelper.clear();
428
374 // HTMLMediaElement and m_asyncEventQueue always become unreachable 429 // HTMLMediaElement and m_asyncEventQueue always become unreachable
375 // together. So HTMLMediaElement and m_asyncEventQueue are destructed in 430 // together. So HTMLMediaElement and m_asyncEventQueue are destructed in
376 // the same GC. We don't need to close it explicitly in Oilpan. 431 // the same GC. We don't need to close it explicitly in Oilpan.
377 m_asyncEventQueue->close(); 432 m_asyncEventQueue->close();
378 433
379 setShouldDelayLoadEvent(false); 434 setShouldDelayLoadEvent(false);
380 435
381 if (m_textTracks) 436 if (m_textTracks)
382 m_textTracks->clearOwner(); 437 m_textTracks->clearOwner();
383 m_audioTracks->shutdown(); 438 m_audioTracks->shutdown();
(...skipping 19 matching lines...) Expand all
403 // m_audioSourceNode is explicitly cleared by AudioNode::dispose(). 458 // m_audioSourceNode is explicitly cleared by AudioNode::dispose().
404 // Since AudioNode::dispose() is guaranteed to be always called before 459 // Since AudioNode::dispose() is guaranteed to be always called before
405 // the AudioNode is destructed, m_audioSourceNode is explicitly cleared 460 // the AudioNode is destructed, m_audioSourceNode is explicitly cleared
406 // even if the AudioNode and the HTMLMediaElement die together. 461 // even if the AudioNode and the HTMLMediaElement die together.
407 ASSERT(!m_audioSourceNode); 462 ASSERT(!m_audioSourceNode);
408 } 463 }
409 464
410 #if ENABLE(OILPAN) 465 #if ENABLE(OILPAN)
411 void HTMLMediaElement::dispose() 466 void HTMLMediaElement::dispose()
412 { 467 {
468 // This must happen before we're destructed.
469 if (m_autoplayHelper)
470 m_autoplayHelper->dispose();
471
413 // If the HTMLMediaElement dies with the Document we are not 472 // If the HTMLMediaElement dies with the Document we are not
414 // allowed to touch the Document to adjust delay load event counts 473 // allowed to touch the Document to adjust delay load event counts
415 // from the destructor, as the Document could have been already 474 // from the destructor, as the Document could have been already
416 // destructed. 475 // destructed.
417 // 476 //
418 // Work around that restriction by accessing the Document from 477 // Work around that restriction by accessing the Document from
419 // a prefinalizer action instead, updating its delayed load count. 478 // a prefinalizer action instead, updating its delayed load count.
420 // If needed - if the Document has been detached and informed its 479 // If needed - if the Document has been detached and informed its
421 // ContextLifecycleObservers (which HTMLMediaElement is) that 480 // ContextLifecycleObservers (which HTMLMediaElement is) that
422 // it is being destroyed, the connection to the Document will 481 // it is being destroyed, the connection to the Document will
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after
663 case WebMimeRegistry::IsSupported: 722 case WebMimeRegistry::IsSupported:
664 canPlay = "probably"; 723 canPlay = "probably";
665 break; 724 break;
666 } 725 }
667 726
668 WTF_LOG(Media, "HTMLMediaElement::canPlayType(%p, %s) -> %s", this, mimeType .utf8().data(), canPlay.utf8().data()); 727 WTF_LOG(Media, "HTMLMediaElement::canPlayType(%p, %s) -> %s", this, mimeType .utf8().data(), canPlay.utf8().data());
669 728
670 return canPlay; 729 return canPlay;
671 } 730 }
672 731
673 void HTMLMediaElement::recordMetricsIfPausing()
674 {
675 // If not playing, then nothing to record.
676 // TODO(liberato): test metrics. this was m_paused.
677 if (m_paused)
678 return;
679
680 const bool bailout = isBailout();
681
682 // Record that play was paused. We don't care if it was autoplay,
683 // play(), or the user manually started it.
684 recordAutoplayMetric(AnyPlaybackPaused);
685 if (bailout)
686 recordAutoplayMetric(AnyPlaybackBailout);
687
688 // If this was a gestureless play, then record that separately.
689 // These cover attr and play() gestureless starts.
690 if (m_initialPlayWithoutUserGesture) {
691 m_initialPlayWithoutUserGesture = false;
692
693 recordAutoplayMetric(AutoplayPaused);
694
695 if (bailout)
696 recordAutoplayMetric(AutoplayBailout);
697 }
698 }
699
700 void HTMLMediaElement::load() 732 void HTMLMediaElement::load()
701 { 733 {
702 WTF_LOG(Media, "HTMLMediaElement::load(%p)", this); 734 WTF_LOG(Media, "HTMLMediaElement::load(%p)", this);
703 735
704 recordMetricsIfPausing(); 736 m_autoplayHelper->loadMethodCalled();
705
706 if (UserGestureIndicator::processingUserGesture() && m_userGestureRequiredFo rPlay) {
707 recordAutoplayMetric(AutoplayEnabledThroughLoad);
708 m_userGestureRequiredForPlay = false;
709 // While usergesture-initiated load()s technically count as autoplayed,
710 // they don't feel like such to the users and hence we don't want to
711 // count them for the purposes of metrics.
712 m_autoplayMediaCounted = true;
713 }
714 737
715 prepareForLoad(); 738 prepareForLoad();
716 loadInternal(); 739 loadInternal();
717 prepareToPlay(); 740 prepareToPlay();
718 } 741 }
719 742
720 void HTMLMediaElement::prepareForLoad() 743 void HTMLMediaElement::prepareForLoad()
721 { 744 {
722 WTF_LOG(Media, "HTMLMediaElement::prepareForLoad(%p)", this); 745 WTF_LOG(Media, "HTMLMediaElement::prepareForLoad(%p)", this);
723 746
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
924 947
925 LocalFrame* frame = document().frame(); 948 LocalFrame* frame = document().frame();
926 if (!frame) { 949 if (!frame) {
927 mediaLoadingFailed(WebMediaPlayer::NetworkStateFormatError); 950 mediaLoadingFailed(WebMediaPlayer::NetworkStateFormatError);
928 return; 951 return;
929 } 952 }
930 953
931 // The resource fetch algorithm 954 // The resource fetch algorithm
932 setNetworkState(NETWORK_LOADING); 955 setNetworkState(NETWORK_LOADING);
933 956
957 m_autoplayHelper->loadingStarted();
958
934 // Set m_currentSrc *before* changing to the cache url, the fact that we are loading from the app 959 // Set m_currentSrc *before* changing to the cache url, the fact that we are loading from the app
935 // cache is an internal detail not exposed through the media element API. 960 // cache is an internal detail not exposed through the media element API.
936 m_currentSrc = url; 961 m_currentSrc = url;
937 962
938 if (m_audioSourceNode) 963 if (m_audioSourceNode)
939 m_audioSourceNode->onCurrentSrcChanged(m_currentSrc); 964 m_audioSourceNode->onCurrentSrcChanged(m_currentSrc);
940 965
941 WTF_LOG(Media, "HTMLMediaElement::loadResource(%p) - m_currentSrc -> %s", th is, urlForLoggingMedia(m_currentSrc).utf8().data()); 966 WTF_LOG(Media, "HTMLMediaElement::loadResource(%p) - m_currentSrc -> %s", th is, urlForLoggingMedia(m_currentSrc).utf8().data());
942 967
943 startProgressEventTimer(); 968 startProgressEventTimer();
944 969
945 // Reset display mode to force a recalculation of what to show because we ar e resetting the player. 970 // Reset display mode to force a recalculation of what to show because we ar e resetting the player.
946 setDisplayMode(Unknown); 971 setDisplayMode(Unknown);
947 972
948 setPlayerPreload(); 973 setPlayerPreload();
949 974
950 if (fastHasAttribute(mutedAttr)) 975 if (fastHasAttribute(mutedAttr))
951 m_muted = true; 976 m_muted = true;
952 updateVolume(); 977 updateVolume();
953 978
954 ASSERT(!m_mediaSource); 979 ASSERT(!m_mediaSource);
955 980
956 bool attemptLoad = true; 981 bool attemptLoad = true;
957 982
958 if (url.protocolIs(mediaSourceBlobProtocol)) { 983 if (url.protocolIs(mediaSourceBlobProtocol)) {
959 if (isMediaStreamURL(url.string())) { 984 if (isMediaStreamURL(url.string())) {
960 m_userGestureRequiredForPlay = false; 985 m_autoplayHelper->removeUserGestureRequirement(GesturelessPlaybackEn abledByStream);
961 } else { 986 } else {
962 m_mediaSource = HTMLMediaSource::lookup(url.string()); 987 m_mediaSource = HTMLMediaSource::lookup(url.string());
963 988
964 if (m_mediaSource) { 989 if (m_mediaSource) {
965 if (!m_mediaSource->attachToElement(this)) { 990 if (!m_mediaSource->attachToElement(this)) {
966 // Forget our reference to the MediaSource, so we leave it a lone 991 // Forget our reference to the MediaSource, so we leave it a lone
967 // while processing remainder of load failure. 992 // while processing remainder of load failure.
968 m_mediaSource = nullptr; 993 m_mediaSource = nullptr;
969 attemptLoad = false; 994 attemptLoad = false;
970 } 995 }
(...skipping 565 matching lines...) Expand 10 before | Expand all | Expand 10 after
1536 if (oldState <= HAVE_CURRENT_DATA) { 1561 if (oldState <= HAVE_CURRENT_DATA) {
1537 scheduleEvent(EventTypeNames::canplay); 1562 scheduleEvent(EventTypeNames::canplay);
1538 if (isPotentiallyPlaying) 1563 if (isPotentiallyPlaying)
1539 scheduleEvent(EventTypeNames::playing); 1564 scheduleEvent(EventTypeNames::playing);
1540 } 1565 }
1541 1566
1542 // Check for autoplay, and record metrics about it if needed. 1567 // Check for autoplay, and record metrics about it if needed.
1543 if (shouldAutoplay(RecordMetricsBehavior::DoRecord)) { 1568 if (shouldAutoplay(RecordMetricsBehavior::DoRecord)) {
1544 // If the autoplay experiment says that it's okay to play now, 1569 // If the autoplay experiment says that it's okay to play now,
1545 // then don't require a user gesture. 1570 // then don't require a user gesture.
1546 m_autoplayHelper.becameReadyToPlay(); 1571 m_autoplayHelper->becameReadyToPlay();
1547 1572
1548 if (!m_userGestureRequiredForPlay) { 1573 if (!m_userGestureRequiredForPlay) {
1549 m_paused = false; 1574 m_paused = false;
1550 invalidateCachedTime(); 1575 invalidateCachedTime();
1551 scheduleEvent(EventTypeNames::play); 1576 scheduleEvent(EventTypeNames::play);
1552 scheduleEvent(EventTypeNames::playing); 1577 scheduleEvent(EventTypeNames::playing);
1553 m_autoplaying = false; 1578 m_autoplaying = false;
1554 } 1579 }
1555 } 1580 }
1556 1581
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
1675 1700
1676 m_lastSeekTime = time; 1701 m_lastSeekTime = time;
1677 m_sentEndEvent = false; 1702 m_sentEndEvent = false;
1678 1703
1679 // 10 - Queue a task to fire a simple event named seeking at the element. 1704 // 10 - Queue a task to fire a simple event named seeking at the element.
1680 scheduleEvent(EventTypeNames::seeking); 1705 scheduleEvent(EventTypeNames::seeking);
1681 1706
1682 // 11 - Set the current playback position to the given new playback position . 1707 // 11 - Set the current playback position to the given new playback position .
1683 webMediaPlayer()->seek(time); 1708 webMediaPlayer()->seek(time);
1684 1709
1685 m_initialPlayWithoutUserGesture = false;
1686
1687 // 14-17 are handled, if necessary, when the engine signals a readystate cha nge or otherwise 1710 // 14-17 are handled, if necessary, when the engine signals a readystate cha nge or otherwise
1688 // satisfies seek completion and signals a time change. 1711 // satisfies seek completion and signals a time change.
1689 } 1712 }
1690 1713
1691 void HTMLMediaElement::finishSeek() 1714 void HTMLMediaElement::finishSeek()
1692 { 1715 {
1693 WTF_LOG(Media, "HTMLMediaElement::finishSeek(%p)", this); 1716 WTF_LOG(Media, "HTMLMediaElement::finishSeek(%p)", this);
1694 1717
1695 // 14 - Set the seeking IDL attribute to false. 1718 // 14 - Set the seeking IDL attribute to false.
1696 m_seeking = false; 1719 m_seeking = false;
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
1858 } 1881 }
1859 1882
1860 bool HTMLMediaElement::autoplay() const 1883 bool HTMLMediaElement::autoplay() const
1861 { 1884 {
1862 return fastHasAttribute(autoplayAttr); 1885 return fastHasAttribute(autoplayAttr);
1863 } 1886 }
1864 1887
1865 bool HTMLMediaElement::shouldAutoplay(const RecordMetricsBehavior recordMetrics) 1888 bool HTMLMediaElement::shouldAutoplay(const RecordMetricsBehavior recordMetrics)
1866 { 1889 {
1867 if (m_autoplaying && m_paused && autoplay()) { 1890 if (m_autoplaying && m_paused && autoplay()) {
1868 if (recordMetrics == RecordMetricsBehavior::DoRecord)
1869 autoplayMediaEncountered();
1870
1871 if (document().isSandboxed(SandboxAutomaticFeatures)) { 1891 if (document().isSandboxed(SandboxAutomaticFeatures)) {
1872 if (recordMetrics == RecordMetricsBehavior::DoRecord) 1892 if (recordMetrics == RecordMetricsBehavior::DoRecord)
1873 recordAutoplayMetric(AutoplayDisabledBySandbox); 1893 m_autoplayHelper->recordSandboxFailure();
1874 return false; 1894 return false;
1875 } 1895 }
1876 1896
1877 return true; 1897 return true;
1878 } 1898 }
1879 1899
1880 return false; 1900 return false;
1881 } 1901 }
1882 1902
1883 String HTMLMediaElement::preload() const 1903 String HTMLMediaElement::preload() const
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1938 1958
1939 WebMediaPlayer::Preload HTMLMediaElement::effectivePreloadType() const 1959 WebMediaPlayer::Preload HTMLMediaElement::effectivePreloadType() const
1940 { 1960 {
1941 return autoplay() ? WebMediaPlayer::PreloadAuto : preloadType(); 1961 return autoplay() ? WebMediaPlayer::PreloadAuto : preloadType();
1942 } 1962 }
1943 1963
1944 void HTMLMediaElement::play() 1964 void HTMLMediaElement::play()
1945 { 1965 {
1946 WTF_LOG(Media, "HTMLMediaElement::play(%p)", this); 1966 WTF_LOG(Media, "HTMLMediaElement::play(%p)", this);
1947 1967
1948 m_autoplayHelper.playMethodCalled(); 1968 m_autoplayHelper->playMethodCalled();
1949 1969
1950 if (!UserGestureIndicator::processingUserGesture()) { 1970 if (!UserGestureIndicator::processingUserGesture()) {
1951 autoplayMediaEncountered();
1952
1953 if (m_userGestureRequiredForPlay) { 1971 if (m_userGestureRequiredForPlay) {
1954 recordAutoplayMetric(PlayMethodFailed); 1972 recordAutoplayMetric(PlayMethodFailed);
1955 String message = ExceptionMessages::failedToExecute("play", "HTMLMed iaElement", "API can only be initiated by a user gesture."); 1973 String message = ExceptionMessages::failedToExecute("play", "HTMLMed iaElement", "API can only be initiated by a user gesture.");
1956 document().addConsoleMessage(ConsoleMessage::create(JSMessageSource, WarningMessageLevel, message)); 1974 document().addConsoleMessage(ConsoleMessage::create(JSMessageSource, WarningMessageLevel, message));
1957 return; 1975 return;
1958 } 1976 }
1959 } else if (m_userGestureRequiredForPlay) { 1977 } else {
1960 if (m_autoplayMediaCounted) 1978 // We ask the helper to remove the gesture requirement for us, so that
1961 recordAutoplayMetric(AutoplayManualStart); 1979 // it can record the reason.
1962 m_userGestureRequiredForPlay = false; 1980 m_autoplayHelper->removeUserGestureRequirement(GesturelessPlaybackEnable dByPlayMethod);
1963 } 1981 }
1964 1982
1965 playInternal(); 1983 playInternal();
1966 } 1984 }
1967 1985
1968 void HTMLMediaElement::playInternal() 1986 void HTMLMediaElement::playInternal()
1969 { 1987 {
1970 WTF_LOG(Media, "HTMLMediaElement::playInternal(%p)", this); 1988 WTF_LOG(Media, "HTMLMediaElement::playInternal(%p)", this);
1971 1989
1972 // Always return the buffering strategy to normal when not paused, 1990 // Always return the buffering strategy to normal when not paused,
(...skipping 20 matching lines...) Expand all
1993 if (m_readyState <= HAVE_CURRENT_DATA) 2011 if (m_readyState <= HAVE_CURRENT_DATA)
1994 scheduleEvent(EventTypeNames::waiting); 2012 scheduleEvent(EventTypeNames::waiting);
1995 else if (m_readyState >= HAVE_FUTURE_DATA) 2013 else if (m_readyState >= HAVE_FUTURE_DATA)
1996 scheduleEvent(EventTypeNames::playing); 2014 scheduleEvent(EventTypeNames::playing);
1997 } 2015 }
1998 m_autoplaying = false; 2016 m_autoplaying = false;
1999 2017
2000 updatePlayState(); 2018 updatePlayState();
2001 } 2019 }
2002 2020
2003 void HTMLMediaElement::autoplayMediaEncountered()
2004 {
2005 if (!m_autoplayMediaCounted) {
2006 m_autoplayMediaCounted = true;
2007 recordAutoplayMetric(AutoplayMediaFound);
2008
2009 if (!m_userGestureRequiredForPlay)
2010 m_initialPlayWithoutUserGesture = true;
2011 }
2012 }
2013
2014 bool HTMLMediaElement::isBailout() const
2015 {
2016 // We count the user as having bailed-out on the video if they watched
2017 // less than one minute and less than 50% of it.
2018 const double playedTime = currentTime();
2019 const double progress = playedTime / duration();
2020 return (playedTime < 60) && (progress < 0.5);
2021 }
2022
2023 void HTMLMediaElement::pause() 2021 void HTMLMediaElement::pause()
2024 { 2022 {
2025 WTF_LOG(Media, "HTMLMediaElement::pause(%p)", this); 2023 WTF_LOG(Media, "HTMLMediaElement::pause(%p)", this);
2026 2024
2027 // Only buffer aggressively on a user-initiated pause. Other types of pauses 2025 // Only buffer aggressively on a user-initiated pause. Other types of pauses
2028 // (which go directly to pauseInternal()) should not cause this behavior. 2026 // (which go directly to pauseInternal()) should not cause this behavior.
2029 if (webMediaPlayer() && UserGestureIndicator::processingUserGesture()) 2027 if (webMediaPlayer() && UserGestureIndicator::processingUserGesture())
2030 webMediaPlayer()->setBufferingStrategy(WebMediaPlayer::BufferingStrategy ::Aggressive); 2028 webMediaPlayer()->setBufferingStrategy(WebMediaPlayer::BufferingStrategy ::Aggressive);
2031 2029
2032 pauseInternal(); 2030 pauseInternal();
2033 } 2031 }
2034 2032
2035 void HTMLMediaElement::pauseInternal() 2033 void HTMLMediaElement::pauseInternal()
2036 { 2034 {
2037 WTF_LOG(Media, "HTMLMediaElement::pauseInternal(%p)", this); 2035 WTF_LOG(Media, "HTMLMediaElement::pauseInternal(%p)", this);
2038 2036
2039 if (m_networkState == NETWORK_EMPTY) 2037 if (m_networkState == NETWORK_EMPTY)
2040 scheduleDelayedAction(LoadMediaResource); 2038 scheduleDelayedAction(LoadMediaResource);
2041 2039
2042 m_autoplayHelper.pauseMethodCalled(); 2040 m_autoplayHelper->pauseMethodCalled();
2043 2041
2044 m_autoplaying = false; 2042 m_autoplaying = false;
2045 2043
2046 if (!m_paused) { 2044 if (!m_paused) {
2047 recordMetricsIfPausing();
2048
2049 m_paused = true; 2045 m_paused = true;
2050 scheduleTimeupdateEvent(false); 2046 scheduleTimeupdateEvent(false);
2051 scheduleEvent(EventTypeNames::pause); 2047 scheduleEvent(EventTypeNames::pause);
2052 } 2048 }
2053 2049
2054 updatePlayState(); 2050 updatePlayState();
2055 } 2051 }
2056 2052
2057 void HTMLMediaElement::requestRemotePlayback() 2053 void HTMLMediaElement::requestRemotePlayback()
2058 { 2054 {
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
2143 2139
2144 void HTMLMediaElement::setMuted(bool muted) 2140 void HTMLMediaElement::setMuted(bool muted)
2145 { 2141 {
2146 WTF_LOG(Media, "HTMLMediaElement::setMuted(%p, %s)", this, boolString(muted) ); 2142 WTF_LOG(Media, "HTMLMediaElement::setMuted(%p, %s)", this, boolString(muted) );
2147 2143
2148 if (m_muted == muted) 2144 if (m_muted == muted)
2149 return; 2145 return;
2150 2146
2151 m_muted = muted; 2147 m_muted = muted;
2152 2148
2153 m_autoplayHelper.mutedChanged(); 2149 m_autoplayHelper->mutedChanged();
2154 2150
2155 updateVolume(); 2151 updateVolume();
2156 2152
2157 scheduleEvent(EventTypeNames::volumechange); 2153 scheduleEvent(EventTypeNames::volumechange);
2158 } 2154 }
2159 2155
2160 void HTMLMediaElement::updateVolume() 2156 void HTMLMediaElement::updateVolume()
2161 { 2157 {
2162 if (webMediaPlayer()) 2158 if (webMediaPlayer())
2163 webMediaPlayer()->setVolume(effectiveMediaVolume()); 2159 webMediaPlayer()->setVolume(effectiveMediaVolume());
(...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after
2739 // If the media element has a loop attribute specified 2735 // If the media element has a loop attribute specified
2740 if (loop()) { 2736 if (loop()) {
2741 m_sentEndEvent = false; 2737 m_sentEndEvent = false;
2742 // then seek to the earliest possible position of the media resourc e and abort these steps. 2738 // then seek to the earliest possible position of the media resourc e and abort these steps.
2743 seek(0); 2739 seek(0);
2744 } else { 2740 } else {
2745 // If the media element has still ended playback, and the direction of playback is still 2741 // If the media element has still ended playback, and the direction of playback is still
2746 // forwards, and paused is false, 2742 // forwards, and paused is false,
2747 if (!m_paused) { 2743 if (!m_paused) {
2748 // changes paused to true and fires a simple event named pause a t the media element. 2744 // changes paused to true and fires a simple event named pause a t the media element.
2745 m_autoplayHelper->playbackEnded();
2749 m_paused = true; 2746 m_paused = true;
2750 scheduleEvent(EventTypeNames::pause); 2747 scheduleEvent(EventTypeNames::pause);
2751 } 2748 }
2752 // Queue a task to fire a simple event named ended at the media elem ent. 2749 // Queue a task to fire a simple event named ended at the media elem ent.
2753 if (!m_sentEndEvent) { 2750 if (!m_sentEndEvent) {
2754 m_sentEndEvent = true; 2751 m_sentEndEvent = true;
2755 scheduleEvent(EventTypeNames::ended); 2752 scheduleEvent(EventTypeNames::ended);
2756 } 2753 }
2757 recordMetricsIfPausing();
2758 } 2754 }
2759 } else { 2755 } else {
2760 m_sentEndEvent = false; 2756 m_sentEndEvent = false;
2761 } 2757 }
2762 2758
2763 updatePlayState(); 2759 updatePlayState();
2764 } 2760 }
2765 2761
2766 void HTMLMediaElement::durationChanged() 2762 void HTMLMediaElement::durationChanged()
2767 { 2763 {
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
2954 if (shouldBePlaying) { 2950 if (shouldBePlaying) {
2955 setDisplayMode(Video); 2951 setDisplayMode(Video);
2956 invalidateCachedTime(); 2952 invalidateCachedTime();
2957 2953
2958 if (!isPlaying) { 2954 if (!isPlaying) {
2959 // Set rate, muted before calling play in case they were set before the media engine was setup. 2955 // Set rate, muted before calling play in case they were set before the media engine was setup.
2960 // The media engine should just stash the rate and muted values sinc e it isn't already playing. 2956 // The media engine should just stash the rate and muted values sinc e it isn't already playing.
2961 webMediaPlayer()->setRate(playbackRate()); 2957 webMediaPlayer()->setRate(playbackRate());
2962 updateVolume(); 2958 updateVolume();
2963 webMediaPlayer()->play(); 2959 webMediaPlayer()->play();
2960 m_autoplayHelper->playbackStarted();
2964 } 2961 }
2965 2962
2966 if (mediaControls()) 2963 if (mediaControls())
2967 mediaControls()->playbackStarted(); 2964 mediaControls()->playbackStarted();
2968 startPlaybackProgressTimer(); 2965 startPlaybackProgressTimer();
2969 m_playing = true; 2966 m_playing = true;
2970 recordAutoplayMetric(AnyPlaybackStarted);
2971 2967
2972 } else { // Should not be playing right now 2968 } else { // Should not be playing right now
2973 if (isPlaying) 2969 if (isPlaying)
2974 webMediaPlayer()->pause(); 2970 webMediaPlayer()->pause();
2971
2975 refreshCachedTime(); 2972 refreshCachedTime();
2976 2973
2977 m_playbackProgressTimer.stop(); 2974 m_playbackProgressTimer.stop();
2978 m_playing = false; 2975 m_playing = false;
2979 double time = currentTime(); 2976 double time = currentTime();
2980 if (time > m_lastSeekTime) 2977 if (time > m_lastSeekTime)
2981 addPlayedRange(m_lastSeekTime, time); 2978 addPlayedRange(m_lastSeekTime, time);
2982 2979
2983 if (couldPlayIfEnoughData()) 2980 if (couldPlayIfEnoughData())
2984 prepareToPlay(); 2981 prepareToPlay();
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
3032 mediaControls()->refreshCastButtonVisibilityWithoutUpdate(); 3029 mediaControls()->refreshCastButtonVisibilityWithoutUpdate();
3033 3030
3034 if (layoutObject()) 3031 if (layoutObject())
3035 layoutObject()->setShouldDoFullPaintInvalidation(); 3032 layoutObject()->setShouldDoFullPaintInvalidation();
3036 } 3033 }
3037 3034
3038 void HTMLMediaElement::stop() 3035 void HTMLMediaElement::stop()
3039 { 3036 {
3040 WTF_LOG(Media, "HTMLMediaElement::stop(%p)", this); 3037 WTF_LOG(Media, "HTMLMediaElement::stop(%p)", this);
3041 3038
3042 recordMetricsIfPausing();
3043
3044 // Close the async event queue so that no events are enqueued. 3039 // Close the async event queue so that no events are enqueued.
3045 cancelPendingEventsAndCallbacks(); 3040 cancelPendingEventsAndCallbacks();
3046 m_asyncEventQueue->close(); 3041 m_asyncEventQueue->close();
3047 3042
3048 // Stop the playback without generating events 3043 // Stop the playback without generating events
3049 clearMediaPlayer(-1); 3044 clearMediaPlayer(-1);
3050 m_readyState = HAVE_NOTHING; 3045 m_readyState = HAVE_NOTHING;
3051 m_readyStateMaximum = HAVE_NOTHING; 3046 m_readyStateMaximum = HAVE_NOTHING;
3052 setNetworkState(NETWORK_EMPTY); 3047 setNetworkState(NETWORK_EMPTY);
3053 setShouldDelayLoadEvent(false); 3048 setShouldDelayLoadEvent(false);
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after
3507 visitor->trace(m_error); 3502 visitor->trace(m_error);
3508 visitor->trace(m_currentSourceNode); 3503 visitor->trace(m_currentSourceNode);
3509 visitor->trace(m_nextChildNodeToConsider); 3504 visitor->trace(m_nextChildNodeToConsider);
3510 visitor->trace(m_mediaSource); 3505 visitor->trace(m_mediaSource);
3511 visitor->trace(m_audioTracks); 3506 visitor->trace(m_audioTracks);
3512 visitor->trace(m_videoTracks); 3507 visitor->trace(m_videoTracks);
3513 visitor->trace(m_cueTimeline); 3508 visitor->trace(m_cueTimeline);
3514 visitor->trace(m_textTracks); 3509 visitor->trace(m_textTracks);
3515 visitor->trace(m_textTracksWhenResourceSelectionBegan); 3510 visitor->trace(m_textTracksWhenResourceSelectionBegan);
3516 visitor->trace(m_audioSourceProvider); 3511 visitor->trace(m_audioSourceProvider);
3512 visitor->trace(m_autoplayHelperClient);
3513 visitor->trace(m_autoplayHelper);
3517 visitor->template registerWeakMembers<HTMLMediaElement, &HTMLMediaElement::c learWeakMembers>(this); 3514 visitor->template registerWeakMembers<HTMLMediaElement, &HTMLMediaElement::c learWeakMembers>(this);
3518 visitor->trace(m_autoplayHelper);
3519 HeapSupplementable<HTMLMediaElement>::trace(visitor); 3515 HeapSupplementable<HTMLMediaElement>::trace(visitor);
3520 #endif 3516 #endif
3521 HTMLElement::trace(visitor); 3517 HTMLElement::trace(visitor);
3522 ActiveDOMObject::trace(visitor); 3518 ActiveDOMObject::trace(visitor);
3523 } 3519 }
3524 3520
3525 void HTMLMediaElement::createPlaceholderTracksIfNecessary() 3521 void HTMLMediaElement::createPlaceholderTracksIfNecessary()
3526 { 3522 {
3527 if (!RuntimeEnabledFeatures::audioVideoTracksEnabled()) 3523 if (!RuntimeEnabledFeatures::audioVideoTracksEnabled())
3528 return; 3524 return;
(...skipping 24 matching lines...) Expand all
3553 bool HTMLMediaElement::isUserGestureRequiredForPlay() const 3549 bool HTMLMediaElement::isUserGestureRequiredForPlay() const
3554 { 3550 {
3555 return m_userGestureRequiredForPlay; 3551 return m_userGestureRequiredForPlay;
3556 } 3552 }
3557 3553
3558 void HTMLMediaElement::removeUserGestureRequirement() 3554 void HTMLMediaElement::removeUserGestureRequirement()
3559 { 3555 {
3560 m_userGestureRequiredForPlay = false; 3556 m_userGestureRequiredForPlay = false;
3561 } 3557 }
3562 3558
3563 void HTMLMediaElement::setInitialPlayWithoutUserGestures(bool value)
3564 {
3565 m_initialPlayWithoutUserGesture = value;
3566 }
3567
3568 void HTMLMediaElement::setNetworkState(NetworkState state) 3559 void HTMLMediaElement::setNetworkState(NetworkState state)
3569 { 3560 {
3570 if (m_networkState != state) { 3561 if (m_networkState != state) {
3571 m_networkState = state; 3562 m_networkState = state;
3572 if (MediaControls* controls = mediaControls()) 3563 if (MediaControls* controls = mediaControls())
3573 controls->networkStateChanged(); 3564 controls->networkStateChanged();
3574 } 3565 }
3575 } 3566 }
3576 3567
3577 void HTMLMediaElement::notifyPositionMayHaveChanged(const IntRect& visibleRect) 3568 void HTMLMediaElement::notifyPositionMayHaveChanged(const IntRect& visibleRect)
3578 { 3569 {
3579 m_autoplayHelper.positionChanged(visibleRect); 3570 m_autoplayHelper->positionChanged(visibleRect);
3580 } 3571 }
3581 3572
3582 void HTMLMediaElement::updatePositionNotificationRegistration() 3573 void HTMLMediaElement::updatePositionNotificationRegistration()
3583 { 3574 {
3584 m_autoplayHelper.updatePositionNotificationRegistration(); 3575 m_autoplayHelper->updatePositionNotificationRegistration();
3585 } 3576 }
3586 3577
3587 // TODO(liberato): remove once autoplay gesture override experiment concludes. 3578 // TODO(liberato): remove once autoplay gesture override experiment concludes.
3588 void HTMLMediaElement::triggerAutoplayViewportCheckForTesting() 3579 void HTMLMediaElement::triggerAutoplayViewportCheckForTesting()
3589 { 3580 {
3590 m_autoplayHelper.triggerAutoplayViewportCheckForTesting(); 3581 if (FrameView* view = document().view())
3582 m_autoplayHelper->positionChanged(view->rootFrameToContents(view->comput eVisibleArea()));
3583 m_autoplayHelper->triggerAutoplayViewportCheckForTesting();
3591 } 3584 }
3592 3585
3593 void HTMLMediaElement::clearWeakMembers(Visitor* visitor) 3586 void HTMLMediaElement::clearWeakMembers(Visitor* visitor)
3594 { 3587 {
3595 if (!Heap::isHeapObjectAlive(m_audioSourceNode)) 3588 if (!Heap::isHeapObjectAlive(m_audioSourceNode))
3596 audioSourceProvider().setClient(nullptr); 3589 audioSourceProvider().setClient(nullptr);
3597 } 3590 }
3598 3591
3599 void HTMLMediaElement::AudioSourceProviderImpl::wrap(WebAudioSourceProvider* pro vider) 3592 void HTMLMediaElement::AudioSourceProviderImpl::wrap(WebAudioSourceProvider* pro vider)
3600 { 3593 {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
3649 DEFINE_TRACE(HTMLMediaElement::AudioClientImpl) 3642 DEFINE_TRACE(HTMLMediaElement::AudioClientImpl)
3650 { 3643 {
3651 visitor->trace(m_client); 3644 visitor->trace(m_client);
3652 } 3645 }
3653 3646
3654 DEFINE_TRACE(HTMLMediaElement::AudioSourceProviderImpl) 3647 DEFINE_TRACE(HTMLMediaElement::AudioSourceProviderImpl)
3655 { 3648 {
3656 visitor->trace(m_client); 3649 visitor->trace(m_client);
3657 } 3650 }
3658 3651
3652 HTMLMediaElement::AutoplayHelperClientImpl::~AutoplayHelperClientImpl()
sof 2016/02/25 18:55:43 nit: it's ok this way, but defining these shorter
3653 {
3654 }
3655
3656 bool HTMLMediaElement::AutoplayHelperClientImpl::isLegacyViewportType()
3657 {
3658 return m_element->document().viewportDescription().isLegacyViewportType();
3659 }
3660
3661 PageVisibilityState HTMLMediaElement::AutoplayHelperClientImpl::pageVisibilitySt ate() const
3662 {
3663 return m_element->document().pageVisibilityState();
3664 }
3665
3666 String HTMLMediaElement::AutoplayHelperClientImpl::autoplayExperimentMode() cons t
3667 {
3668 String mode;
3669 if (m_element->document().settings())
3670 mode = m_element->document().settings()->autoplayExperimentMode();
3671
3672 return mode;
3673 }
3674
3675 void HTMLMediaElement::AutoplayHelperClientImpl::setRequestPositionUpdates(bool request)
3676 {
3677 if (LayoutObject* layoutObject = m_element->layoutObject()) {
3678 LayoutMedia* layoutMedia = toLayoutMedia(layoutObject);
3679 layoutMedia->setRequestPositionUpdates(request);
3680 }
3681 }
3682
3683 IntRect HTMLMediaElement::AutoplayHelperClientImpl::absoluteBoundingBoxRect() co nst
3684 {
3685 IntRect result;
3686 if (LayoutObject* object = m_element->layoutObject())
3687 result = object->absoluteBoundingBoxRect();
3688 return result;
3689 }
3690
3659 } // namespace blink 3691 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698