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

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: fixed trace. 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 :
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 = AutoplayExperimentHelper::Client::RecordMetric sBehavior;
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(RecordMetricsBehavior behavior) override { return m_elem ent->shouldAutoplay(behavior); }
280 bool isHTMLVideoElement() const override { return m_element->isHTMLVideoElem ent(); }
281 bool isHTMLAudioElement() const override { return m_element->isHTMLAudioElem ent(); }
282
283 // Document
284 bool isLegacyViewportType() override;
285 PageVisibilityState pageVisibilityState() const override;
286 String autoplayExperimentMode() const override;
287
288 // LayoutObject
289 void setRequestPositionUpdates(bool) override;
290 IntRect absoluteBoundingBoxRect() const override;
291
292 DEFINE_INLINE_VIRTUAL_TRACE() {
293 visitor->trace(m_element);
294 Client::trace(visitor);
295 }
296
297 private:
298 AutoplayHelperClientImpl(HTMLMediaElement* element) : m_element(element) {}
299
300 RawPtrWillBeMember<HTMLMediaElement> m_element;
301 };
302
303
256 void HTMLMediaElement::recordAutoplayMetric(AutoplayMetrics metric) 304 void HTMLMediaElement::recordAutoplayMetric(AutoplayMetrics metric)
257 { 305 {
258 DEFINE_STATIC_LOCAL(EnumerationHistogram, autoplayHistogram, ("Blink.MediaEl ement.Autoplay", NumberOfAutoplayMetrics)); 306 DEFINE_STATIC_LOCAL(EnumerationHistogram, autoplayHistogram, ("Blink.MediaEl ement.Autoplay", NumberOfAutoplayMetrics));
259 autoplayHistogram.count(metric); 307 autoplayHistogram.count(metric);
260 } 308 }
261 309
262 WebMimeRegistry::SupportsType HTMLMediaElement::supportsType(const ContentType& contentType) 310 WebMimeRegistry::SupportsType HTMLMediaElement::supportsType(const ContentType& contentType)
263 { 311 {
264 DEFINE_STATIC_LOCAL(const String, codecs, ("codecs")); 312 DEFINE_STATIC_LOCAL(const String, codecs, ("codecs"));
265 313
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 , m_seeking(false) 382 , m_seeking(false)
335 , m_sentStalledEvent(false) 383 , m_sentStalledEvent(false)
336 , m_sentEndEvent(false) 384 , m_sentEndEvent(false)
337 , m_closedCaptionsVisible(false) 385 , m_closedCaptionsVisible(false)
338 , m_havePreparedToPlay(false) 386 , m_havePreparedToPlay(false)
339 , m_tracksAreReady(true) 387 , m_tracksAreReady(true)
340 , m_processingPreferenceChange(false) 388 , m_processingPreferenceChange(false)
341 , m_remoteRoutesAvailable(false) 389 , m_remoteRoutesAvailable(false)
342 , m_playingRemotely(false) 390 , m_playingRemotely(false)
343 , m_isFinalizing(false) 391 , m_isFinalizing(false)
344 , m_initialPlayWithoutUserGesture(false)
345 , m_autoplayMediaCounted(false)
346 , m_inOverlayFullscreenVideo(false) 392 , m_inOverlayFullscreenVideo(false)
347 , m_audioTracks(AudioTrackList::create(*this)) 393 , m_audioTracks(AudioTrackList::create(*this))
348 , m_videoTracks(VideoTrackList::create(*this)) 394 , m_videoTracks(VideoTrackList::create(*this))
349 , m_textTracks(nullptr) 395 , m_textTracks(nullptr)
350 , m_audioSourceNode(nullptr) 396 , m_audioSourceNode(nullptr)
351 , m_autoplayHelper(*this) 397 , m_autoplayHelperClient(AutoplayHelperClientImpl::create(this))
398 , m_autoplayHelper(AutoplayExperimentHelper::create(m_autoplayHelperClient))
352 { 399 {
353 #if ENABLE(OILPAN) 400 #if ENABLE(OILPAN)
354 ThreadState::current()->registerPreFinalizer(this); 401 ThreadState::current()->registerPreFinalizer(this);
355 #endif 402 #endif
356 ASSERT(RuntimeEnabledFeatures::mediaEnabled()); 403 ASSERT(RuntimeEnabledFeatures::mediaEnabled());
357 404
358 WTF_LOG(Media, "HTMLMediaElement::HTMLMediaElement(%p)", this); 405 WTF_LOG(Media, "HTMLMediaElement::HTMLMediaElement(%p)", this);
359 406
360 if (document.settings() && document.settings()->mediaPlaybackRequiresUserGes ture()) 407 if (document.settings() && document.settings()->mediaPlaybackRequiresUserGes ture())
361 m_userGestureRequiredForPlay = true; 408 m_userGestureRequiredForPlay = true;
362 409
363 setHasCustomStyleCallbacks(); 410 setHasCustomStyleCallbacks();
364 addElementToDocumentMap(this, &document); 411 addElementToDocumentMap(this, &document);
365 412
366 UseCounter::count(document, UseCounter::HTMLMediaElement); 413 UseCounter::count(document, UseCounter::HTMLMediaElement);
367 } 414 }
368 415
369 HTMLMediaElement::~HTMLMediaElement() 416 HTMLMediaElement::~HTMLMediaElement()
370 { 417 {
371 WTF_LOG(Media, "HTMLMediaElement::~HTMLMediaElement(%p)", this); 418 WTF_LOG(Media, "HTMLMediaElement::~HTMLMediaElement(%p)", this);
372 419
373 #if !ENABLE(OILPAN) 420 #if !ENABLE(OILPAN)
421 // Destruction of the autoplay helper requires the client, so be sure that
422 // this happens before the client is destructed.
423 if (m_autoplayHelper)
424 m_autoplayHelper.clear();
425
374 // HTMLMediaElement and m_asyncEventQueue always become unreachable 426 // HTMLMediaElement and m_asyncEventQueue always become unreachable
375 // together. So HTMLMediaElement and m_asyncEventQueue are destructed in 427 // together. So HTMLMediaElement and m_asyncEventQueue are destructed in
376 // the same GC. We don't need to close it explicitly in Oilpan. 428 // the same GC. We don't need to close it explicitly in Oilpan.
377 m_asyncEventQueue->close(); 429 m_asyncEventQueue->close();
378 430
379 setShouldDelayLoadEvent(false); 431 setShouldDelayLoadEvent(false);
380 432
381 if (m_textTracks) 433 if (m_textTracks)
382 m_textTracks->clearOwner(); 434 m_textTracks->clearOwner();
383 m_audioTracks->shutdown(); 435 m_audioTracks->shutdown();
(...skipping 19 matching lines...) Expand all
403 // m_audioSourceNode is explicitly cleared by AudioNode::dispose(). 455 // m_audioSourceNode is explicitly cleared by AudioNode::dispose().
404 // Since AudioNode::dispose() is guaranteed to be always called before 456 // Since AudioNode::dispose() is guaranteed to be always called before
405 // the AudioNode is destructed, m_audioSourceNode is explicitly cleared 457 // the AudioNode is destructed, m_audioSourceNode is explicitly cleared
406 // even if the AudioNode and the HTMLMediaElement die together. 458 // even if the AudioNode and the HTMLMediaElement die together.
407 ASSERT(!m_audioSourceNode); 459 ASSERT(!m_audioSourceNode);
408 } 460 }
409 461
410 #if ENABLE(OILPAN) 462 #if ENABLE(OILPAN)
411 void HTMLMediaElement::dispose() 463 void HTMLMediaElement::dispose()
412 { 464 {
465 // This must happen before we're destructed.
466 if (m_autoplayHelper)
467 m_autoplayHelper->dispose();
468
413 // If the HTMLMediaElement dies with the Document we are not 469 // If the HTMLMediaElement dies with the Document we are not
414 // allowed to touch the Document to adjust delay load event counts 470 // allowed to touch the Document to adjust delay load event counts
415 // from the destructor, as the Document could have been already 471 // from the destructor, as the Document could have been already
416 // destructed. 472 // destructed.
417 // 473 //
418 // Work around that restriction by accessing the Document from 474 // Work around that restriction by accessing the Document from
419 // a prefinalizer action instead, updating its delayed load count. 475 // a prefinalizer action instead, updating its delayed load count.
420 // If needed - if the Document has been detached and informed its 476 // If needed - if the Document has been detached and informed its
421 // ContextLifecycleObservers (which HTMLMediaElement is) that 477 // ContextLifecycleObservers (which HTMLMediaElement is) that
422 // it is being destroyed, the connection to the Document will 478 // 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: 719 case WebMimeRegistry::IsSupported:
664 canPlay = "probably"; 720 canPlay = "probably";
665 break; 721 break;
666 } 722 }
667 723
668 WTF_LOG(Media, "HTMLMediaElement::canPlayType(%p, %s) -> %s", this, mimeType .utf8().data(), canPlay.utf8().data()); 724 WTF_LOG(Media, "HTMLMediaElement::canPlayType(%p, %s) -> %s", this, mimeType .utf8().data(), canPlay.utf8().data());
669 725
670 return canPlay; 726 return canPlay;
671 } 727 }
672 728
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() 729 void HTMLMediaElement::load()
701 { 730 {
702 WTF_LOG(Media, "HTMLMediaElement::load(%p)", this); 731 WTF_LOG(Media, "HTMLMediaElement::load(%p)", this);
703 732
704 recordMetricsIfPausing(); 733 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 734
715 prepareForLoad(); 735 prepareForLoad();
716 loadInternal(); 736 loadInternal();
717 prepareToPlay(); 737 prepareToPlay();
718 } 738 }
719 739
720 void HTMLMediaElement::prepareForLoad() 740 void HTMLMediaElement::prepareForLoad()
721 { 741 {
722 WTF_LOG(Media, "HTMLMediaElement::prepareForLoad(%p)", this); 742 WTF_LOG(Media, "HTMLMediaElement::prepareForLoad(%p)", this);
723 743
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
924 944
925 LocalFrame* frame = document().frame(); 945 LocalFrame* frame = document().frame();
926 if (!frame) { 946 if (!frame) {
927 mediaLoadingFailed(WebMediaPlayer::NetworkStateFormatError); 947 mediaLoadingFailed(WebMediaPlayer::NetworkStateFormatError);
928 return; 948 return;
929 } 949 }
930 950
931 // The resource fetch algorithm 951 // The resource fetch algorithm
932 setNetworkState(NETWORK_LOADING); 952 setNetworkState(NETWORK_LOADING);
933 953
954 m_autoplayHelper->loadingStarted();
955
934 // Set m_currentSrc *before* changing to the cache url, the fact that we are loading from the app 956 // 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. 957 // cache is an internal detail not exposed through the media element API.
936 m_currentSrc = url; 958 m_currentSrc = url;
937 959
938 if (m_audioSourceNode) 960 if (m_audioSourceNode)
939 m_audioSourceNode->onCurrentSrcChanged(m_currentSrc); 961 m_audioSourceNode->onCurrentSrcChanged(m_currentSrc);
940 962
941 WTF_LOG(Media, "HTMLMediaElement::loadResource(%p) - m_currentSrc -> %s", th is, urlForLoggingMedia(m_currentSrc).utf8().data()); 963 WTF_LOG(Media, "HTMLMediaElement::loadResource(%p) - m_currentSrc -> %s", th is, urlForLoggingMedia(m_currentSrc).utf8().data());
942 964
943 startProgressEventTimer(); 965 startProgressEventTimer();
944 966
945 // Reset display mode to force a recalculation of what to show because we ar e resetting the player. 967 // Reset display mode to force a recalculation of what to show because we ar e resetting the player.
946 setDisplayMode(Unknown); 968 setDisplayMode(Unknown);
947 969
948 setPlayerPreload(); 970 setPlayerPreload();
949 971
950 if (fastHasAttribute(mutedAttr)) 972 if (fastHasAttribute(mutedAttr))
951 m_muted = true; 973 m_muted = true;
952 updateVolume(); 974 updateVolume();
953 975
954 ASSERT(!m_mediaSource); 976 ASSERT(!m_mediaSource);
955 977
956 bool attemptLoad = true; 978 bool attemptLoad = true;
957 979
958 if (url.protocolIs(mediaSourceBlobProtocol)) { 980 if (url.protocolIs(mediaSourceBlobProtocol)) {
959 if (isMediaStreamURL(url.string())) { 981 if (isMediaStreamURL(url.string())) {
960 m_userGestureRequiredForPlay = false; 982 m_autoplayHelper->removeUserGestureRequirement(GesturelessPlaybackEn abledByStream);
961 } else { 983 } else {
962 m_mediaSource = HTMLMediaSource::lookup(url.string()); 984 m_mediaSource = HTMLMediaSource::lookup(url.string());
963 985
964 if (m_mediaSource) { 986 if (m_mediaSource) {
965 if (!m_mediaSource->attachToElement(this)) { 987 if (!m_mediaSource->attachToElement(this)) {
966 // Forget our reference to the MediaSource, so we leave it a lone 988 // Forget our reference to the MediaSource, so we leave it a lone
967 // while processing remainder of load failure. 989 // while processing remainder of load failure.
968 m_mediaSource = nullptr; 990 m_mediaSource = nullptr;
969 attemptLoad = false; 991 attemptLoad = false;
970 } 992 }
(...skipping 565 matching lines...) Expand 10 before | Expand all | Expand 10 after
1536 if (oldState <= HAVE_CURRENT_DATA) { 1558 if (oldState <= HAVE_CURRENT_DATA) {
1537 scheduleEvent(EventTypeNames::canplay); 1559 scheduleEvent(EventTypeNames::canplay);
1538 if (isPotentiallyPlaying) 1560 if (isPotentiallyPlaying)
1539 scheduleEvent(EventTypeNames::playing); 1561 scheduleEvent(EventTypeNames::playing);
1540 } 1562 }
1541 1563
1542 // Check for autoplay, and record metrics about it if needed. 1564 // Check for autoplay, and record metrics about it if needed.
1543 if (shouldAutoplay(RecordMetricsBehavior::DoRecord)) { 1565 if (shouldAutoplay(RecordMetricsBehavior::DoRecord)) {
1544 // If the autoplay experiment says that it's okay to play now, 1566 // If the autoplay experiment says that it's okay to play now,
1545 // then don't require a user gesture. 1567 // then don't require a user gesture.
1546 m_autoplayHelper.becameReadyToPlay(); 1568 m_autoplayHelper->becameReadyToPlay();
1547 1569
1548 if (!m_userGestureRequiredForPlay) { 1570 if (!m_userGestureRequiredForPlay) {
1549 m_paused = false; 1571 m_paused = false;
1550 invalidateCachedTime(); 1572 invalidateCachedTime();
1551 scheduleEvent(EventTypeNames::play); 1573 scheduleEvent(EventTypeNames::play);
1552 scheduleEvent(EventTypeNames::playing); 1574 scheduleEvent(EventTypeNames::playing);
1553 m_autoplaying = false; 1575 m_autoplaying = false;
1554 } 1576 }
1555 } 1577 }
1556 1578
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
1675 1697
1676 m_lastSeekTime = time; 1698 m_lastSeekTime = time;
1677 m_sentEndEvent = false; 1699 m_sentEndEvent = false;
1678 1700
1679 // 10 - Queue a task to fire a simple event named seeking at the element. 1701 // 10 - Queue a task to fire a simple event named seeking at the element.
1680 scheduleEvent(EventTypeNames::seeking); 1702 scheduleEvent(EventTypeNames::seeking);
1681 1703
1682 // 11 - Set the current playback position to the given new playback position . 1704 // 11 - Set the current playback position to the given new playback position .
1683 webMediaPlayer()->seek(time); 1705 webMediaPlayer()->seek(time);
1684 1706
1685 m_initialPlayWithoutUserGesture = false;
1686
1687 // 14-17 are handled, if necessary, when the engine signals a readystate cha nge or otherwise 1707 // 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. 1708 // satisfies seek completion and signals a time change.
1689 } 1709 }
1690 1710
1691 void HTMLMediaElement::finishSeek() 1711 void HTMLMediaElement::finishSeek()
1692 { 1712 {
1693 WTF_LOG(Media, "HTMLMediaElement::finishSeek(%p)", this); 1713 WTF_LOG(Media, "HTMLMediaElement::finishSeek(%p)", this);
1694 1714
1695 // 14 - Set the seeking IDL attribute to false. 1715 // 14 - Set the seeking IDL attribute to false.
1696 m_seeking = false; 1716 m_seeking = false;
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
1858 } 1878 }
1859 1879
1860 bool HTMLMediaElement::autoplay() const 1880 bool HTMLMediaElement::autoplay() const
1861 { 1881 {
1862 return fastHasAttribute(autoplayAttr); 1882 return fastHasAttribute(autoplayAttr);
1863 } 1883 }
1864 1884
1865 bool HTMLMediaElement::shouldAutoplay(const RecordMetricsBehavior recordMetrics) 1885 bool HTMLMediaElement::shouldAutoplay(const RecordMetricsBehavior recordMetrics)
1866 { 1886 {
1867 if (m_autoplaying && m_paused && autoplay()) { 1887 if (m_autoplaying && m_paused && autoplay()) {
1868 if (recordMetrics == RecordMetricsBehavior::DoRecord)
1869 autoplayMediaEncountered();
1870
1871 if (document().isSandboxed(SandboxAutomaticFeatures)) { 1888 if (document().isSandboxed(SandboxAutomaticFeatures)) {
1872 if (recordMetrics == RecordMetricsBehavior::DoRecord) 1889 if (recordMetrics == RecordMetricsBehavior::DoRecord)
1873 recordAutoplayMetric(AutoplayDisabledBySandbox); 1890 m_autoplayHelper->recordSandboxFailure();
1874 return false; 1891 return false;
1875 } 1892 }
1876 1893
1877 return true; 1894 return true;
1878 } 1895 }
1879 1896
1880 return false; 1897 return false;
1881 } 1898 }
1882 1899
1883 String HTMLMediaElement::preload() const 1900 String HTMLMediaElement::preload() const
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1938 1955
1939 WebMediaPlayer::Preload HTMLMediaElement::effectivePreloadType() const 1956 WebMediaPlayer::Preload HTMLMediaElement::effectivePreloadType() const
1940 { 1957 {
1941 return autoplay() ? WebMediaPlayer::PreloadAuto : preloadType(); 1958 return autoplay() ? WebMediaPlayer::PreloadAuto : preloadType();
1942 } 1959 }
1943 1960
1944 void HTMLMediaElement::play() 1961 void HTMLMediaElement::play()
1945 { 1962 {
1946 WTF_LOG(Media, "HTMLMediaElement::play(%p)", this); 1963 WTF_LOG(Media, "HTMLMediaElement::play(%p)", this);
1947 1964
1948 m_autoplayHelper.playMethodCalled(); 1965 m_autoplayHelper->playMethodCalled();
1949 1966
1950 if (!UserGestureIndicator::processingUserGesture()) { 1967 if (!UserGestureIndicator::processingUserGesture()) {
1951 autoplayMediaEncountered();
1952
1953 if (m_userGestureRequiredForPlay) { 1968 if (m_userGestureRequiredForPlay) {
1954 recordAutoplayMetric(PlayMethodFailed); 1969 recordAutoplayMetric(PlayMethodFailed);
1955 String message = ExceptionMessages::failedToExecute("play", "HTMLMed iaElement", "API can only be initiated by a user gesture."); 1970 String message = ExceptionMessages::failedToExecute("play", "HTMLMed iaElement", "API can only be initiated by a user gesture.");
1956 document().addConsoleMessage(ConsoleMessage::create(JSMessageSource, WarningMessageLevel, message)); 1971 document().addConsoleMessage(ConsoleMessage::create(JSMessageSource, WarningMessageLevel, message));
1957 return; 1972 return;
1958 } 1973 }
1959 } else if (m_userGestureRequiredForPlay) { 1974 } else {
1960 if (m_autoplayMediaCounted) 1975 // We ask the helper to remove the gesture requirement for us, so that
1961 recordAutoplayMetric(AutoplayManualStart); 1976 // it can record the reason.
1962 m_userGestureRequiredForPlay = false; 1977 m_autoplayHelper->removeUserGestureRequirement(GesturelessPlaybackEnable dByPlayMethod);
1963 } 1978 }
1964 1979
1965 playInternal(); 1980 playInternal();
1966 } 1981 }
1967 1982
1968 void HTMLMediaElement::playInternal() 1983 void HTMLMediaElement::playInternal()
1969 { 1984 {
1970 WTF_LOG(Media, "HTMLMediaElement::playInternal(%p)", this); 1985 WTF_LOG(Media, "HTMLMediaElement::playInternal(%p)", this);
1971 1986
1972 // Always return the buffering strategy to normal when not paused, 1987 // Always return the buffering strategy to normal when not paused,
(...skipping 20 matching lines...) Expand all
1993 if (m_readyState <= HAVE_CURRENT_DATA) 2008 if (m_readyState <= HAVE_CURRENT_DATA)
1994 scheduleEvent(EventTypeNames::waiting); 2009 scheduleEvent(EventTypeNames::waiting);
1995 else if (m_readyState >= HAVE_FUTURE_DATA) 2010 else if (m_readyState >= HAVE_FUTURE_DATA)
1996 scheduleEvent(EventTypeNames::playing); 2011 scheduleEvent(EventTypeNames::playing);
1997 } 2012 }
1998 m_autoplaying = false; 2013 m_autoplaying = false;
1999 2014
2000 updatePlayState(); 2015 updatePlayState();
2001 } 2016 }
2002 2017
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() 2018 void HTMLMediaElement::pause()
2024 { 2019 {
2025 WTF_LOG(Media, "HTMLMediaElement::pause(%p)", this); 2020 WTF_LOG(Media, "HTMLMediaElement::pause(%p)", this);
2026 2021
2027 // Only buffer aggressively on a user-initiated pause. Other types of pauses 2022 // Only buffer aggressively on a user-initiated pause. Other types of pauses
2028 // (which go directly to pauseInternal()) should not cause this behavior. 2023 // (which go directly to pauseInternal()) should not cause this behavior.
2029 if (webMediaPlayer() && UserGestureIndicator::processingUserGesture()) 2024 if (webMediaPlayer() && UserGestureIndicator::processingUserGesture())
2030 webMediaPlayer()->setBufferingStrategy(WebMediaPlayer::BufferingStrategy ::Aggressive); 2025 webMediaPlayer()->setBufferingStrategy(WebMediaPlayer::BufferingStrategy ::Aggressive);
2031 2026
2032 pauseInternal(); 2027 pauseInternal();
2033 } 2028 }
2034 2029
2035 void HTMLMediaElement::pauseInternal() 2030 void HTMLMediaElement::pauseInternal()
2036 { 2031 {
2037 WTF_LOG(Media, "HTMLMediaElement::pauseInternal(%p)", this); 2032 WTF_LOG(Media, "HTMLMediaElement::pauseInternal(%p)", this);
2038 2033
2039 if (m_networkState == NETWORK_EMPTY) 2034 if (m_networkState == NETWORK_EMPTY)
2040 scheduleDelayedAction(LoadMediaResource); 2035 scheduleDelayedAction(LoadMediaResource);
2041 2036
2042 m_autoplayHelper.pauseMethodCalled(); 2037 m_autoplayHelper->pauseMethodCalled();
2043 2038
2044 m_autoplaying = false; 2039 m_autoplaying = false;
2045 2040
2046 if (!m_paused) { 2041 if (!m_paused) {
2047 recordMetricsIfPausing();
2048
2049 m_paused = true; 2042 m_paused = true;
2050 scheduleTimeupdateEvent(false); 2043 scheduleTimeupdateEvent(false);
2051 scheduleEvent(EventTypeNames::pause); 2044 scheduleEvent(EventTypeNames::pause);
2052 } 2045 }
2053 2046
2054 updatePlayState(); 2047 updatePlayState();
2055 } 2048 }
2056 2049
2057 void HTMLMediaElement::requestRemotePlayback() 2050 void HTMLMediaElement::requestRemotePlayback()
2058 { 2051 {
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
2143 2136
2144 void HTMLMediaElement::setMuted(bool muted) 2137 void HTMLMediaElement::setMuted(bool muted)
2145 { 2138 {
2146 WTF_LOG(Media, "HTMLMediaElement::setMuted(%p, %s)", this, boolString(muted) ); 2139 WTF_LOG(Media, "HTMLMediaElement::setMuted(%p, %s)", this, boolString(muted) );
2147 2140
2148 if (m_muted == muted) 2141 if (m_muted == muted)
2149 return; 2142 return;
2150 2143
2151 m_muted = muted; 2144 m_muted = muted;
2152 2145
2153 m_autoplayHelper.mutedChanged(); 2146 m_autoplayHelper->mutedChanged();
2154 2147
2155 updateVolume(); 2148 updateVolume();
2156 2149
2157 scheduleEvent(EventTypeNames::volumechange); 2150 scheduleEvent(EventTypeNames::volumechange);
2158 } 2151 }
2159 2152
2160 void HTMLMediaElement::updateVolume() 2153 void HTMLMediaElement::updateVolume()
2161 { 2154 {
2162 if (webMediaPlayer()) 2155 if (webMediaPlayer())
2163 webMediaPlayer()->setVolume(effectiveMediaVolume()); 2156 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 2732 // If the media element has a loop attribute specified
2740 if (loop()) { 2733 if (loop()) {
2741 m_sentEndEvent = false; 2734 m_sentEndEvent = false;
2742 // then seek to the earliest possible position of the media resourc e and abort these steps. 2735 // then seek to the earliest possible position of the media resourc e and abort these steps.
2743 seek(0); 2736 seek(0);
2744 } else { 2737 } else {
2745 // If the media element has still ended playback, and the direction of playback is still 2738 // If the media element has still ended playback, and the direction of playback is still
2746 // forwards, and paused is false, 2739 // forwards, and paused is false,
2747 if (!m_paused) { 2740 if (!m_paused) {
2748 // changes paused to true and fires a simple event named pause a t the media element. 2741 // changes paused to true and fires a simple event named pause a t the media element.
2742 m_autoplayHelper->playbackEnded();
2749 m_paused = true; 2743 m_paused = true;
2750 scheduleEvent(EventTypeNames::pause); 2744 scheduleEvent(EventTypeNames::pause);
2751 } 2745 }
2752 // Queue a task to fire a simple event named ended at the media elem ent. 2746 // Queue a task to fire a simple event named ended at the media elem ent.
2753 if (!m_sentEndEvent) { 2747 if (!m_sentEndEvent) {
2754 m_sentEndEvent = true; 2748 m_sentEndEvent = true;
2755 scheduleEvent(EventTypeNames::ended); 2749 scheduleEvent(EventTypeNames::ended);
2756 } 2750 }
2757 recordMetricsIfPausing();
2758 } 2751 }
2759 } else { 2752 } else {
2760 m_sentEndEvent = false; 2753 m_sentEndEvent = false;
2761 } 2754 }
2762 2755
2763 updatePlayState(); 2756 updatePlayState();
2764 } 2757 }
2765 2758
2766 void HTMLMediaElement::durationChanged() 2759 void HTMLMediaElement::durationChanged()
2767 { 2760 {
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
2954 if (shouldBePlaying) { 2947 if (shouldBePlaying) {
2955 setDisplayMode(Video); 2948 setDisplayMode(Video);
2956 invalidateCachedTime(); 2949 invalidateCachedTime();
2957 2950
2958 if (!isPlaying) { 2951 if (!isPlaying) {
2959 // Set rate, muted before calling play in case they were set before the media engine was setup. 2952 // 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. 2953 // The media engine should just stash the rate and muted values sinc e it isn't already playing.
2961 webMediaPlayer()->setRate(playbackRate()); 2954 webMediaPlayer()->setRate(playbackRate());
2962 updateVolume(); 2955 updateVolume();
2963 webMediaPlayer()->play(); 2956 webMediaPlayer()->play();
2957 m_autoplayHelper->playbackStarted();
2964 } 2958 }
2965 2959
2966 if (mediaControls()) 2960 if (mediaControls())
2967 mediaControls()->playbackStarted(); 2961 mediaControls()->playbackStarted();
2968 startPlaybackProgressTimer(); 2962 startPlaybackProgressTimer();
2969 m_playing = true; 2963 m_playing = true;
2970 recordAutoplayMetric(AnyPlaybackStarted);
2971 2964
2972 } else { // Should not be playing right now 2965 } else { // Should not be playing right now
2973 if (isPlaying) 2966 if (isPlaying)
2974 webMediaPlayer()->pause(); 2967 webMediaPlayer()->pause();
2968
2975 refreshCachedTime(); 2969 refreshCachedTime();
2976 2970
2977 m_playbackProgressTimer.stop(); 2971 m_playbackProgressTimer.stop();
2978 m_playing = false; 2972 m_playing = false;
2979 double time = currentTime(); 2973 double time = currentTime();
2980 if (time > m_lastSeekTime) 2974 if (time > m_lastSeekTime)
2981 addPlayedRange(m_lastSeekTime, time); 2975 addPlayedRange(m_lastSeekTime, time);
2982 2976
2983 if (couldPlayIfEnoughData()) 2977 if (couldPlayIfEnoughData())
2984 prepareToPlay(); 2978 prepareToPlay();
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
3032 mediaControls()->refreshCastButtonVisibilityWithoutUpdate(); 3026 mediaControls()->refreshCastButtonVisibilityWithoutUpdate();
3033 3027
3034 if (layoutObject()) 3028 if (layoutObject())
3035 layoutObject()->setShouldDoFullPaintInvalidation(); 3029 layoutObject()->setShouldDoFullPaintInvalidation();
3036 } 3030 }
3037 3031
3038 void HTMLMediaElement::stop() 3032 void HTMLMediaElement::stop()
3039 { 3033 {
3040 WTF_LOG(Media, "HTMLMediaElement::stop(%p)", this); 3034 WTF_LOG(Media, "HTMLMediaElement::stop(%p)", this);
3041 3035
3042 recordMetricsIfPausing();
3043
3044 // Close the async event queue so that no events are enqueued. 3036 // Close the async event queue so that no events are enqueued.
3045 cancelPendingEventsAndCallbacks(); 3037 cancelPendingEventsAndCallbacks();
3046 m_asyncEventQueue->close(); 3038 m_asyncEventQueue->close();
3047 3039
3048 // Stop the playback without generating events 3040 // Stop the playback without generating events
3049 clearMediaPlayer(-1); 3041 clearMediaPlayer(-1);
3050 m_readyState = HAVE_NOTHING; 3042 m_readyState = HAVE_NOTHING;
3051 m_readyStateMaximum = HAVE_NOTHING; 3043 m_readyStateMaximum = HAVE_NOTHING;
3052 setNetworkState(NETWORK_EMPTY); 3044 setNetworkState(NETWORK_EMPTY);
3053 setShouldDelayLoadEvent(false); 3045 setShouldDelayLoadEvent(false);
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after
3507 visitor->trace(m_error); 3499 visitor->trace(m_error);
3508 visitor->trace(m_currentSourceNode); 3500 visitor->trace(m_currentSourceNode);
3509 visitor->trace(m_nextChildNodeToConsider); 3501 visitor->trace(m_nextChildNodeToConsider);
3510 visitor->trace(m_mediaSource); 3502 visitor->trace(m_mediaSource);
3511 visitor->trace(m_audioTracks); 3503 visitor->trace(m_audioTracks);
3512 visitor->trace(m_videoTracks); 3504 visitor->trace(m_videoTracks);
3513 visitor->trace(m_cueTimeline); 3505 visitor->trace(m_cueTimeline);
3514 visitor->trace(m_textTracks); 3506 visitor->trace(m_textTracks);
3515 visitor->trace(m_textTracksWhenResourceSelectionBegan); 3507 visitor->trace(m_textTracksWhenResourceSelectionBegan);
3516 visitor->trace(m_audioSourceProvider); 3508 visitor->trace(m_audioSourceProvider);
3509 visitor->trace(m_autoplayHelperClient);
3510 visitor->trace(m_autoplayHelper);
3517 visitor->template registerWeakMembers<HTMLMediaElement, &HTMLMediaElement::c learWeakMembers>(this); 3511 visitor->template registerWeakMembers<HTMLMediaElement, &HTMLMediaElement::c learWeakMembers>(this);
3518 visitor->trace(m_autoplayHelper);
3519 HeapSupplementable<HTMLMediaElement>::trace(visitor); 3512 HeapSupplementable<HTMLMediaElement>::trace(visitor);
3520 #endif 3513 #endif
3521 HTMLElement::trace(visitor); 3514 HTMLElement::trace(visitor);
3522 ActiveDOMObject::trace(visitor); 3515 ActiveDOMObject::trace(visitor);
3523 } 3516 }
3524 3517
3525 void HTMLMediaElement::createPlaceholderTracksIfNecessary() 3518 void HTMLMediaElement::createPlaceholderTracksIfNecessary()
3526 { 3519 {
3527 if (!RuntimeEnabledFeatures::audioVideoTracksEnabled()) 3520 if (!RuntimeEnabledFeatures::audioVideoTracksEnabled())
3528 return; 3521 return;
(...skipping 24 matching lines...) Expand all
3553 bool HTMLMediaElement::isUserGestureRequiredForPlay() const 3546 bool HTMLMediaElement::isUserGestureRequiredForPlay() const
3554 { 3547 {
3555 return m_userGestureRequiredForPlay; 3548 return m_userGestureRequiredForPlay;
3556 } 3549 }
3557 3550
3558 void HTMLMediaElement::removeUserGestureRequirement() 3551 void HTMLMediaElement::removeUserGestureRequirement()
3559 { 3552 {
3560 m_userGestureRequiredForPlay = false; 3553 m_userGestureRequiredForPlay = false;
3561 } 3554 }
3562 3555
3563 void HTMLMediaElement::setInitialPlayWithoutUserGestures(bool value)
3564 {
3565 m_initialPlayWithoutUserGesture = value;
3566 }
3567
3568 void HTMLMediaElement::setNetworkState(NetworkState state) 3556 void HTMLMediaElement::setNetworkState(NetworkState state)
3569 { 3557 {
3570 if (m_networkState != state) { 3558 if (m_networkState != state) {
3571 m_networkState = state; 3559 m_networkState = state;
3572 if (MediaControls* controls = mediaControls()) 3560 if (MediaControls* controls = mediaControls())
3573 controls->networkStateChanged(); 3561 controls->networkStateChanged();
3574 } 3562 }
3575 } 3563 }
3576 3564
3577 void HTMLMediaElement::notifyPositionMayHaveChanged(const IntRect& visibleRect) 3565 void HTMLMediaElement::notifyPositionMayHaveChanged(const IntRect& visibleRect)
3578 { 3566 {
3579 m_autoplayHelper.positionChanged(visibleRect); 3567 m_autoplayHelper->positionChanged(visibleRect);
3580 } 3568 }
3581 3569
3582 void HTMLMediaElement::updatePositionNotificationRegistration() 3570 void HTMLMediaElement::updatePositionNotificationRegistration()
3583 { 3571 {
3584 m_autoplayHelper.updatePositionNotificationRegistration(); 3572 m_autoplayHelper->updatePositionNotificationRegistration();
3585 } 3573 }
3586 3574
3587 // TODO(liberato): remove once autoplay gesture override experiment concludes. 3575 // TODO(liberato): remove once autoplay gesture override experiment concludes.
3588 void HTMLMediaElement::triggerAutoplayViewportCheckForTesting() 3576 void HTMLMediaElement::triggerAutoplayViewportCheckForTesting()
3589 { 3577 {
3590 m_autoplayHelper.triggerAutoplayViewportCheckForTesting(); 3578 if (FrameView* view = document().view())
3579 m_autoplayHelper->positionChanged(view->rootFrameToContents(view->comput eVisibleArea()));
3580 m_autoplayHelper->triggerAutoplayViewportCheckForTesting();
3591 } 3581 }
3592 3582
3593 void HTMLMediaElement::clearWeakMembers(Visitor* visitor) 3583 void HTMLMediaElement::clearWeakMembers(Visitor* visitor)
3594 { 3584 {
3595 if (!Heap::isHeapObjectAlive(m_audioSourceNode)) 3585 if (!Heap::isHeapObjectAlive(m_audioSourceNode))
3596 audioSourceProvider().setClient(nullptr); 3586 audioSourceProvider().setClient(nullptr);
3597 } 3587 }
3598 3588
3599 void HTMLMediaElement::AudioSourceProviderImpl::wrap(WebAudioSourceProvider* pro vider) 3589 void HTMLMediaElement::AudioSourceProviderImpl::wrap(WebAudioSourceProvider* pro vider)
3600 { 3590 {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
3649 DEFINE_TRACE(HTMLMediaElement::AudioClientImpl) 3639 DEFINE_TRACE(HTMLMediaElement::AudioClientImpl)
3650 { 3640 {
3651 visitor->trace(m_client); 3641 visitor->trace(m_client);
3652 } 3642 }
3653 3643
3654 DEFINE_TRACE(HTMLMediaElement::AudioSourceProviderImpl) 3644 DEFINE_TRACE(HTMLMediaElement::AudioSourceProviderImpl)
3655 { 3645 {
3656 visitor->trace(m_client); 3646 visitor->trace(m_client);
3657 } 3647 }
3658 3648
3649 HTMLMediaElement::AutoplayHelperClientImpl::~AutoplayHelperClientImpl()
3650 {
3651 }
3652
3653 bool HTMLMediaElement::AutoplayHelperClientImpl::isLegacyViewportType()
3654 {
3655 return m_element->document().viewportDescription().isLegacyViewportType();
3656 }
3657
3658 PageVisibilityState HTMLMediaElement::AutoplayHelperClientImpl::pageVisibilitySt ate() const
3659 {
3660 return m_element->document().pageVisibilityState();
3661 }
3662
3663 String HTMLMediaElement::AutoplayHelperClientImpl::autoplayExperimentMode() cons t
3664 {
3665 String mode;
3666 if (m_element->document().settings())
3667 mode = m_element->document().settings()->autoplayExperimentMode();
3668
3669 return mode;
3670 }
3671
3672 void HTMLMediaElement::AutoplayHelperClientImpl::setRequestPositionUpdates(bool request)
3673 {
3674 if (LayoutObject* layoutObject = m_element->layoutObject()) {
3675 LayoutMedia* layoutMedia = toLayoutMedia(layoutObject);
3676 layoutMedia->setRequestPositionUpdates(request);
3677 }
3678 }
3679
3680 IntRect HTMLMediaElement::AutoplayHelperClientImpl::absoluteBoundingBoxRect() co nst
3681 {
3682 IntRect result;
3683 if (LayoutObject* object = m_element->layoutObject())
3684 result = object->absoluteBoundingBoxRect();
3685 return result;
3686 }
3687
3659 } // namespace blink 3688 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698