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

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

Issue 2524443002: Adding Rappor metrics for disabling cross-origin autoplay with sound experiment (Closed)
Patch Set: rebased Created 4 years 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
« no previous file with comments | « third_party/WebKit/Source/core/html/HTMLMediaElement.h ('k') | tools/metrics/rappor/rappor.xml » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights 2 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights
3 * reserved. 3 * reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 m_loadState(WaitingForSource), 387 m_loadState(WaitingForSource),
388 m_deferredLoadState(NotDeferred), 388 m_deferredLoadState(NotDeferred),
389 m_deferredLoadTimer(this, &HTMLMediaElement::deferredLoadTimerFired), 389 m_deferredLoadTimer(this, &HTMLMediaElement::deferredLoadTimerFired),
390 m_webLayer(nullptr), 390 m_webLayer(nullptr),
391 m_displayMode(Unknown), 391 m_displayMode(Unknown),
392 m_officialPlaybackPosition(0), 392 m_officialPlaybackPosition(0),
393 m_officialPlaybackPositionNeedsUpdate(true), 393 m_officialPlaybackPositionNeedsUpdate(true),
394 m_fragmentEndTime(std::numeric_limits<double>::quiet_NaN()), 394 m_fragmentEndTime(std::numeric_limits<double>::quiet_NaN()),
395 m_pendingActionFlags(0), 395 m_pendingActionFlags(0),
396 m_lockedPendingUserGesture(false), 396 m_lockedPendingUserGesture(false),
397 m_lockedPendingUserGestureIfCrossOriginExperimentEnabled(true),
397 m_playing(false), 398 m_playing(false),
398 m_shouldDelayLoadEvent(false), 399 m_shouldDelayLoadEvent(false),
399 m_haveFiredLoadedData(false), 400 m_haveFiredLoadedData(false),
400 m_autoplaying(true), 401 m_autoplaying(true),
401 m_muted(false), 402 m_muted(false),
402 m_paused(true), 403 m_paused(true),
403 m_seeking(false), 404 m_seeking(false),
404 m_sentStalledEvent(false), 405 m_sentStalledEvent(false),
405 m_ignorePreloadNone(false), 406 m_ignorePreloadNone(false),
406 m_textTracksVisible(false), 407 m_textTracksVisible(false),
407 m_shouldPerformAutomaticTrackSelection(true), 408 m_shouldPerformAutomaticTrackSelection(true),
408 m_tracksAreReady(true), 409 m_tracksAreReady(true),
409 m_processingPreferenceChange(false), 410 m_processingPreferenceChange(false),
410 m_playingRemotely(false), 411 m_playingRemotely(false),
411 m_inOverlayFullscreenVideo(false), 412 m_inOverlayFullscreenVideo(false),
412 m_mostlyFillingViewport(false), 413 m_mostlyFillingViewport(false),
413 m_audioTracks(this, AudioTrackList::create(*this)), 414 m_audioTracks(this, AudioTrackList::create(*this)),
414 m_videoTracks(this, VideoTrackList::create(*this)), 415 m_videoTracks(this, VideoTrackList::create(*this)),
415 m_textTracks(this, nullptr), 416 m_textTracks(this, nullptr),
416 m_audioSourceNode(nullptr), 417 m_audioSourceNode(nullptr),
417 m_autoplayUmaHelper(AutoplayUmaHelper::create(this)), 418 m_autoplayUmaHelper(AutoplayUmaHelper::create(this)),
418 m_remotePlaybackClient(nullptr), 419 m_remotePlaybackClient(nullptr),
419 m_autoplayVisibilityObserver(nullptr) { 420 m_autoplayVisibilityObserver(nullptr) {
420 ThreadState::current()->registerPreFinalizer(this); 421 ThreadState::current()->registerPreFinalizer(this);
421 422
422 BLINK_MEDIA_LOG << "HTMLMediaElement(" << (void*)this << ")"; 423 BLINK_MEDIA_LOG << "HTMLMediaElement(" << (void*)this << ")";
423 424
424 m_lockedPendingUserGesture = computeLockedPendingUserGesture(document); 425 m_lockedPendingUserGesture = computeLockedPendingUserGesture(document);
426 m_lockedPendingUserGestureIfCrossOriginExperimentEnabled =
427 isDocumentCrossOrigin(document);
425 428
426 LocalFrame* frame = document.frame(); 429 LocalFrame* frame = document.frame();
427 if (frame) { 430 if (frame) {
428 m_remotePlaybackClient = 431 m_remotePlaybackClient =
429 frame->loader().client()->createWebRemotePlaybackClient(*this); 432 frame->loader().client()->createWebRemotePlaybackClient(*this);
430 } 433 }
431 434
432 setHasCustomStyleCallbacks(); 435 setHasCustomStyleCallbacks();
433 addElementToDocumentMap(this, &document); 436 addElementToDocumentMap(this, &document);
434 437
(...skipping 26 matching lines...) Expand all
461 void HTMLMediaElement::didMoveToNewDocument(Document& oldDocument) { 464 void HTMLMediaElement::didMoveToNewDocument(Document& oldDocument) {
462 BLINK_MEDIA_LOG << "didMoveToNewDocument(" << (void*)this << ")"; 465 BLINK_MEDIA_LOG << "didMoveToNewDocument(" << (void*)this << ")";
463 466
464 m_autoplayUmaHelper->didMoveToNewDocument(oldDocument); 467 m_autoplayUmaHelper->didMoveToNewDocument(oldDocument);
465 // If any experiment is enabled, then we want to enable a user gesture by 468 // If any experiment is enabled, then we want to enable a user gesture by
466 // default, otherwise the experiment does nothing. 469 // default, otherwise the experiment does nothing.
467 bool oldDocumentRequiresUserGesture = 470 bool oldDocumentRequiresUserGesture =
468 computeLockedPendingUserGesture(oldDocument); 471 computeLockedPendingUserGesture(oldDocument);
469 bool newDocumentRequiresUserGesture = 472 bool newDocumentRequiresUserGesture =
470 computeLockedPendingUserGesture(document()); 473 computeLockedPendingUserGesture(document());
471 if (newDocumentRequiresUserGesture && !oldDocumentRequiresUserGesture) { 474 if (newDocumentRequiresUserGesture && !oldDocumentRequiresUserGesture)
472 m_lockedPendingUserGesture = true; 475 m_lockedPendingUserGesture = true;
473 }
474 476
475 if (m_shouldDelayLoadEvent) { 477 if (m_shouldDelayLoadEvent) {
476 document().incrementLoadEventDelayCount(); 478 document().incrementLoadEventDelayCount();
477 // Note: Keeping the load event delay count increment on oldDocument that 479 // Note: Keeping the load event delay count increment on oldDocument that
478 // was added when m_shouldDelayLoadEvent was set so that destruction of 480 // was added when m_shouldDelayLoadEvent was set so that destruction of
479 // m_webMediaPlayer can not cause load event dispatching in oldDocument. 481 // m_webMediaPlayer can not cause load event dispatching in oldDocument.
480 } else { 482 } else {
481 // Incrementing the load event delay count so that destruction of 483 // Incrementing the load event delay count so that destruction of
482 // m_webMediaPlayer can not cause load event dispatching in oldDocument. 484 // m_webMediaPlayer can not cause load event dispatching in oldDocument.
483 oldDocument.incrementLoadEventDelayCount(); 485 oldDocument.incrementLoadEventDelayCount();
484 } 486 }
485 487
488 if (isDocumentCrossOrigin(document()) && !isDocumentCrossOrigin(oldDocument))
489 m_lockedPendingUserGestureIfCrossOriginExperimentEnabled = true;
490
486 removeElementFromDocumentMap(this, &oldDocument); 491 removeElementFromDocumentMap(this, &oldDocument);
487 addElementToDocumentMap(this, &document()); 492 addElementToDocumentMap(this, &document());
488 493
489 // FIXME: This is a temporary fix to prevent this object from causing the 494 // FIXME: This is a temporary fix to prevent this object from causing the
490 // MediaPlayer to dereference LocalFrame and FrameLoader pointers from the 495 // MediaPlayer to dereference LocalFrame and FrameLoader pointers from the
491 // previous document. This restarts the load, as if the src attribute had been 496 // previous document. This restarts the load, as if the src attribute had been
492 // set. A proper fix would provide a mechanism to allow this object to 497 // set. A proper fix would provide a mechanism to allow this object to
493 // refresh the MediaPlayer's LocalFrame and FrameLoader references on document 498 // refresh the MediaPlayer's LocalFrame and FrameLoader references on document
494 // changes so that playback can be resumed properly. 499 // changes so that playback can be resumed properly.
495 m_ignorePreloadNone = false; 500 m_ignorePreloadNone = false;
(...skipping 827 matching lines...) Expand 10 before | Expand all | Expand 10 after
1323 // didPassCORSAccessCheck() means it was a successful CORS-enabled fetch 1328 // didPassCORSAccessCheck() means it was a successful CORS-enabled fetch
1324 // (vs. non-CORS-enabled or failed). 1329 // (vs. non-CORS-enabled or failed).
1325 // taintsCanvas() does checkAccess() on the URL plus allow data sources, 1330 // taintsCanvas() does checkAccess() on the URL plus allow data sources,
1326 // to ensure that it is not a URL that requires CORS (basically same 1331 // to ensure that it is not a URL that requires CORS (basically same
1327 // origin). 1332 // origin).
1328 return hasSingleSecurityOrigin() && 1333 return hasSingleSecurityOrigin() &&
1329 ((webMediaPlayer() && webMediaPlayer()->didPassCORSAccessCheck()) || 1334 ((webMediaPlayer() && webMediaPlayer()->didPassCORSAccessCheck()) ||
1330 !origin->taintsCanvas(currentSrc())); 1335 !origin->taintsCanvas(currentSrc()));
1331 } 1336 }
1332 1337
1338 bool HTMLMediaElement::isInCrossOriginFrame() const {
1339 return isDocumentCrossOrigin(document());
1340 }
1341
1333 void HTMLMediaElement::startProgressEventTimer() { 1342 void HTMLMediaElement::startProgressEventTimer() {
1334 if (m_progressEventTimer.isActive()) 1343 if (m_progressEventTimer.isActive())
1335 return; 1344 return;
1336 1345
1337 m_previousProgressTime = WTF::currentTime(); 1346 m_previousProgressTime = WTF::currentTime();
1338 // 350ms is not magic, it is in the spec! 1347 // 350ms is not magic, it is in the spec!
1339 m_progressEventTimer.startRepeating(0.350, BLINK_FROM_HERE); 1348 m_progressEventTimer.startRepeating(0.350, BLINK_FROM_HERE);
1340 } 1349 }
1341 1350
1342 void HTMLMediaElement::waitForSourceChange() { 1351 void HTMLMediaElement::waitForSourceChange() {
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
1684 scheduleEvent(EventTypeNames::canplay); 1693 scheduleEvent(EventTypeNames::canplay);
1685 if (isPotentiallyPlaying) 1694 if (isPotentiallyPlaying)
1686 scheduleNotifyPlaying(); 1695 scheduleNotifyPlaying();
1687 } 1696 }
1688 1697
1689 // Check for autoplay, and record metrics about it if needed. 1698 // Check for autoplay, and record metrics about it if needed.
1690 if (shouldAutoplay()) { 1699 if (shouldAutoplay()) {
1691 m_autoplayUmaHelper->onAutoplayInitiated(AutoplaySource::Attribute); 1700 m_autoplayUmaHelper->onAutoplayInitiated(AutoplaySource::Attribute);
1692 1701
1693 if (!isGestureNeededForPlayback()) { 1702 if (!isGestureNeededForPlayback()) {
1703 if (isGestureNeededForPlaybackIfCrossOriginExperimentEnabled()) {
1704 m_autoplayUmaHelper->recordCrossOriginAutoplayResult(
1705 CrossOriginAutoplayResult::AutoplayBlocked);
1706 } else {
1707 m_autoplayUmaHelper->recordCrossOriginAutoplayResult(
1708 CrossOriginAutoplayResult::AutoplayAllowed);
1709 }
1694 if (isHTMLVideoElement() && muted() && 1710 if (isHTMLVideoElement() && muted() &&
1695 RuntimeEnabledFeatures::autoplayMutedVideosEnabled()) { 1711 RuntimeEnabledFeatures::autoplayMutedVideosEnabled()) {
1696 // We might end up in a situation where the previous 1712 // We might end up in a situation where the previous
1697 // observer didn't had time to fire yet. We can avoid 1713 // observer didn't had time to fire yet. We can avoid
1698 // creating a new one in this case. 1714 // creating a new one in this case.
1699 if (!m_autoplayVisibilityObserver) { 1715 if (!m_autoplayVisibilityObserver) {
1700 m_autoplayVisibilityObserver = new ElementVisibilityObserver( 1716 m_autoplayVisibilityObserver = new ElementVisibilityObserver(
1701 this, 1717 this,
1702 WTF::bind(&HTMLMediaElement::onVisibilityChangedForAutoplay, 1718 WTF::bind(&HTMLMediaElement::onVisibilityChangedForAutoplay,
1703 wrapWeakPersistent(this))); 1719 wrapWeakPersistent(this)));
1704 m_autoplayVisibilityObserver->start(); 1720 m_autoplayVisibilityObserver->start();
1705 } 1721 }
1706 } else { 1722 } else {
1707 m_paused = false; 1723 m_paused = false;
1708 scheduleEvent(EventTypeNames::play); 1724 scheduleEvent(EventTypeNames::play);
1709 scheduleNotifyPlaying(); 1725 scheduleNotifyPlaying();
1710 m_autoplaying = false; 1726 m_autoplaying = false;
1711 } 1727 }
1728 } else {
1729 m_autoplayUmaHelper->recordCrossOriginAutoplayResult(
1730 CrossOriginAutoplayResult::AutoplayBlocked);
1712 } 1731 }
1713 } 1732 }
1714 1733
1715 scheduleEvent(EventTypeNames::canplaythrough); 1734 scheduleEvent(EventTypeNames::canplaythrough);
1716 1735
1717 shouldUpdateDisplayState = true; 1736 shouldUpdateDisplayState = true;
1718 } 1737 }
1719 1738
1720 if (shouldUpdateDisplayState) 1739 if (shouldUpdateDisplayState)
1721 updateDisplayState(); 1740 updateDisplayState();
(...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after
2178 if (!UserGestureIndicator::processingUserGesture()) { 2197 if (!UserGestureIndicator::processingUserGesture()) {
2179 m_autoplayUmaHelper->onAutoplayInitiated(AutoplaySource::Method); 2198 m_autoplayUmaHelper->onAutoplayInitiated(AutoplaySource::Method);
2180 if (isGestureNeededForPlayback()) { 2199 if (isGestureNeededForPlayback()) {
2181 // If we're already playing, then this play would do nothing anyway. 2200 // If we're already playing, then this play would do nothing anyway.
2182 // Call playInternal to handle scheduling the promise resolution. 2201 // Call playInternal to handle scheduling the promise resolution.
2183 if (!m_paused) { 2202 if (!m_paused) {
2184 playInternal(); 2203 playInternal();
2185 return nullptr; 2204 return nullptr;
2186 } 2205 }
2187 2206
2207 m_autoplayUmaHelper->recordCrossOriginAutoplayResult(
2208 CrossOriginAutoplayResult::AutoplayBlocked);
2188 String message = ExceptionMessages::failedToExecute( 2209 String message = ExceptionMessages::failedToExecute(
2189 "play", "HTMLMediaElement", 2210 "play", "HTMLMediaElement",
2190 "API can only be initiated by a user gesture."); 2211 "API can only be initiated by a user gesture.");
2191 document().addConsoleMessage(ConsoleMessage::create( 2212 document().addConsoleMessage(ConsoleMessage::create(
2192 JSMessageSource, WarningMessageLevel, message)); 2213 JSMessageSource, WarningMessageLevel, message));
2193 return NotAllowedError; 2214 return NotAllowedError;
2215 } else {
2216 if (isGestureNeededForPlaybackIfCrossOriginExperimentEnabled()) {
2217 m_autoplayUmaHelper->recordCrossOriginAutoplayResult(
2218 CrossOriginAutoplayResult::AutoplayBlocked);
2219 } else {
2220 m_autoplayUmaHelper->recordCrossOriginAutoplayResult(
2221 CrossOriginAutoplayResult::AutoplayAllowed);
2222 }
2194 } 2223 }
2195 } else { 2224 } else {
2225 m_autoplayUmaHelper->recordCrossOriginAutoplayResult(
2226 CrossOriginAutoplayResult::PlayedWithGesture);
2196 UserGestureIndicator::utilizeUserGesture(); 2227 UserGestureIndicator::utilizeUserGesture();
2197 unlockUserGesture(); 2228 unlockUserGesture();
2198 } 2229 }
2199 2230
2200 if (m_error && m_error->code() == MediaError::kMediaErrSrcNotSupported) 2231 if (m_error && m_error->code() == MediaError::kMediaErrSrcNotSupported)
2201 return NotSupportedError; 2232 return NotSupportedError;
2202 2233
2203 playInternal(); 2234 playInternal();
2204 2235
2205 return nullptr; 2236 return nullptr;
(...skipping 1573 matching lines...) Expand 10 before | Expand all | Expand 10 after
3779 if (videoTracks().length() > 0 && videoTracks().selectedIndex() == -1) 3810 if (videoTracks().length() > 0 && videoTracks().selectedIndex() == -1)
3780 videoTracks().anonymousIndexedGetter(0)->setSelected(true); 3811 videoTracks().anonymousIndexedGetter(0)->setSelected(true);
3781 } 3812 }
3782 3813
3783 bool HTMLMediaElement::isLockedPendingUserGesture() const { 3814 bool HTMLMediaElement::isLockedPendingUserGesture() const {
3784 return m_lockedPendingUserGesture; 3815 return m_lockedPendingUserGesture;
3785 } 3816 }
3786 3817
3787 void HTMLMediaElement::unlockUserGesture() { 3818 void HTMLMediaElement::unlockUserGesture() {
3788 m_lockedPendingUserGesture = false; 3819 m_lockedPendingUserGesture = false;
3820 m_lockedPendingUserGestureIfCrossOriginExperimentEnabled = false;
3789 } 3821 }
3790 3822
3791 bool HTMLMediaElement::isGestureNeededForPlayback() const { 3823 bool HTMLMediaElement::isGestureNeededForPlayback() const {
3792 if (!m_lockedPendingUserGesture) 3824 if (!m_lockedPendingUserGesture)
3793 return false; 3825 return false;
3794 3826
3827 return isGestureNeededForPlaybackIfPendingUserGestureIsLocked();
3828 }
3829
3830 bool HTMLMediaElement::
3831 isGestureNeededForPlaybackIfCrossOriginExperimentEnabled() const {
3832 if (!m_lockedPendingUserGestureIfCrossOriginExperimentEnabled)
3833 return false;
3834
3835 return isGestureNeededForPlaybackIfPendingUserGestureIsLocked();
3836 }
3837
3838 bool HTMLMediaElement::isGestureNeededForPlaybackIfPendingUserGestureIsLocked()
3839 const {
3795 if (loadType() == WebMediaPlayer::LoadTypeMediaStream) 3840 if (loadType() == WebMediaPlayer::LoadTypeMediaStream)
3796 return false; 3841 return false;
3797 3842
3798 // We want to allow muted video to autoplay if: 3843 // We want to allow muted video to autoplay if:
3799 // - the flag is enabled; 3844 // - the flag is enabled;
3800 // - Data Saver is not enabled; 3845 // - Data Saver is not enabled;
3801 // - Preload was not disabled (low end devices); 3846 // - Preload was not disabled (low end devices);
3802 // - Autoplay is enabled in settings; 3847 // - Autoplay is enabled in settings;
3803 if (isHTMLVideoElement() && muted() && 3848 if (isHTMLVideoElement() && muted() &&
3804 RuntimeEnabledFeatures::autoplayMutedVideosEnabled() && 3849 RuntimeEnabledFeatures::autoplayMutedVideosEnabled() &&
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
4065 kMostlyFillViewportBecomeStableSeconds, BLINK_FROM_HERE); 4110 kMostlyFillViewportBecomeStableSeconds, BLINK_FROM_HERE);
4066 } 4111 }
4067 4112
4068 void HTMLMediaElement::viewportFillDebouncerTimerFired(TimerBase*) { 4113 void HTMLMediaElement::viewportFillDebouncerTimerFired(TimerBase*) {
4069 m_mostlyFillingViewport = true; 4114 m_mostlyFillingViewport = true;
4070 if (m_webMediaPlayer) 4115 if (m_webMediaPlayer)
4071 m_webMediaPlayer->becameDominantVisibleContent(m_mostlyFillingViewport); 4116 m_webMediaPlayer->becameDominantVisibleContent(m_mostlyFillingViewport);
4072 } 4117 }
4073 4118
4074 } // namespace blink 4119 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/html/HTMLMediaElement.h ('k') | tools/metrics/rappor/rappor.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698