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

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: new implementation 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
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 419 matching lines...) Expand 10 before | Expand all | Expand 10 after
430 m_loadState(WaitingForSource), 430 m_loadState(WaitingForSource),
431 m_deferredLoadState(NotDeferred), 431 m_deferredLoadState(NotDeferred),
432 m_deferredLoadTimer(this, &HTMLMediaElement::deferredLoadTimerFired), 432 m_deferredLoadTimer(this, &HTMLMediaElement::deferredLoadTimerFired),
433 m_webLayer(nullptr), 433 m_webLayer(nullptr),
434 m_displayMode(Unknown), 434 m_displayMode(Unknown),
435 m_officialPlaybackPosition(0), 435 m_officialPlaybackPosition(0),
436 m_officialPlaybackPositionNeedsUpdate(true), 436 m_officialPlaybackPositionNeedsUpdate(true),
437 m_fragmentEndTime(std::numeric_limits<double>::quiet_NaN()), 437 m_fragmentEndTime(std::numeric_limits<double>::quiet_NaN()),
438 m_pendingActionFlags(0), 438 m_pendingActionFlags(0),
439 m_lockedPendingUserGesture(false), 439 m_lockedPendingUserGesture(false),
440 m_lockedPendingUserGestureIfCrossOriginExperimentEnabled(true),
440 m_playing(false), 441 m_playing(false),
441 m_shouldDelayLoadEvent(false), 442 m_shouldDelayLoadEvent(false),
442 m_haveFiredLoadedData(false), 443 m_haveFiredLoadedData(false),
443 m_autoplaying(true), 444 m_autoplaying(true),
444 m_muted(false), 445 m_muted(false),
445 m_paused(true), 446 m_paused(true),
446 m_seeking(false), 447 m_seeking(false),
447 m_sentStalledEvent(false), 448 m_sentStalledEvent(false),
448 m_ignorePreloadNone(false), 449 m_ignorePreloadNone(false),
449 m_textTracksVisible(false), 450 m_textTracksVisible(false),
(...skipping 10 matching lines...) Expand all
460 m_autoplayHelper( 461 m_autoplayHelper(
461 AutoplayExperimentHelper::create(m_autoplayHelperClient.get())), 462 AutoplayExperimentHelper::create(m_autoplayHelperClient.get())),
462 m_autoplayUmaHelper(AutoplayUmaHelper::create(this)), 463 m_autoplayUmaHelper(AutoplayUmaHelper::create(this)),
463 m_remotePlaybackClient(nullptr), 464 m_remotePlaybackClient(nullptr),
464 m_autoplayVisibilityObserver(nullptr) { 465 m_autoplayVisibilityObserver(nullptr) {
465 ThreadState::current()->registerPreFinalizer(this); 466 ThreadState::current()->registerPreFinalizer(this);
466 467
467 BLINK_MEDIA_LOG << "HTMLMediaElement(" << (void*)this << ")"; 468 BLINK_MEDIA_LOG << "HTMLMediaElement(" << (void*)this << ")";
468 469
469 m_lockedPendingUserGesture = computeLockedPendingUserGesture(document); 470 m_lockedPendingUserGesture = computeLockedPendingUserGesture(document);
471 m_lockedPendingUserGestureIfCrossOriginExperimentEnabled =
472 isDocumentCrossOrigin(document);
470 473
471 LocalFrame* frame = document.frame(); 474 LocalFrame* frame = document.frame();
472 if (frame) { 475 if (frame) {
473 m_remotePlaybackClient = 476 m_remotePlaybackClient =
474 frame->loader().client()->createWebRemotePlaybackClient(*this); 477 frame->loader().client()->createWebRemotePlaybackClient(*this);
475 } 478 }
476 479
477 setHasCustomStyleCallbacks(); 480 setHasCustomStyleCallbacks();
478 addElementToDocumentMap(this, &document); 481 addElementToDocumentMap(this, &document);
479 482
(...skipping 26 matching lines...) Expand all
506 void HTMLMediaElement::didMoveToNewDocument(Document& oldDocument) { 509 void HTMLMediaElement::didMoveToNewDocument(Document& oldDocument) {
507 BLINK_MEDIA_LOG << "didMoveToNewDocument(" << (void*)this << ")"; 510 BLINK_MEDIA_LOG << "didMoveToNewDocument(" << (void*)this << ")";
508 511
509 m_autoplayUmaHelper->didMoveToNewDocument(oldDocument); 512 m_autoplayUmaHelper->didMoveToNewDocument(oldDocument);
510 // If any experiment is enabled, then we want to enable a user gesture by 513 // If any experiment is enabled, then we want to enable a user gesture by
511 // default, otherwise the experiment does nothing. 514 // default, otherwise the experiment does nothing.
512 bool oldDocumentRequiresUserGesture = 515 bool oldDocumentRequiresUserGesture =
513 computeLockedPendingUserGesture(oldDocument); 516 computeLockedPendingUserGesture(oldDocument);
514 bool newDocumentRequiresUserGesture = 517 bool newDocumentRequiresUserGesture =
515 computeLockedPendingUserGesture(document()); 518 computeLockedPendingUserGesture(document());
516 if (newDocumentRequiresUserGesture && !oldDocumentRequiresUserGesture) { 519 if (newDocumentRequiresUserGesture && !oldDocumentRequiresUserGesture)
517 m_lockedPendingUserGesture = true; 520 m_lockedPendingUserGesture = true;
518 }
519 521
520 if (m_shouldDelayLoadEvent) { 522 if (m_shouldDelayLoadEvent) {
521 document().incrementLoadEventDelayCount(); 523 document().incrementLoadEventDelayCount();
522 // Note: Keeping the load event delay count increment on oldDocument that 524 // Note: Keeping the load event delay count increment on oldDocument that
523 // was added when m_shouldDelayLoadEvent was set so that destruction of 525 // was added when m_shouldDelayLoadEvent was set so that destruction of
524 // m_webMediaPlayer can not cause load event dispatching in oldDocument. 526 // m_webMediaPlayer can not cause load event dispatching in oldDocument.
525 } else { 527 } else {
526 // Incrementing the load event delay count so that destruction of 528 // Incrementing the load event delay count so that destruction of
527 // m_webMediaPlayer can not cause load event dispatching in oldDocument. 529 // m_webMediaPlayer can not cause load event dispatching in oldDocument.
528 oldDocument.incrementLoadEventDelayCount(); 530 oldDocument.incrementLoadEventDelayCount();
529 } 531 }
530 532
533 if (isDocumentCrossOrigin(document()) && !isDocumentCrossOrigin(oldDocument))
534 m_lockedPendingUserGestureIfCrossOriginExperimentEnabled = true;
whywhat 2016/11/29 21:42:04 should you make it false in the case the new docum
Zhiqiang Zhang (Slow) 2016/11/30 17:30:52 Please see the other reply.
535
531 removeElementFromDocumentMap(this, &oldDocument); 536 removeElementFromDocumentMap(this, &oldDocument);
532 addElementToDocumentMap(this, &document()); 537 addElementToDocumentMap(this, &document());
533 538
534 // FIXME: This is a temporary fix to prevent this object from causing the 539 // FIXME: This is a temporary fix to prevent this object from causing the
535 // MediaPlayer to dereference LocalFrame and FrameLoader pointers from the 540 // MediaPlayer to dereference LocalFrame and FrameLoader pointers from the
536 // previous document. This restarts the load, as if the src attribute had been 541 // previous document. This restarts the load, as if the src attribute had been
537 // set. A proper fix would provide a mechanism to allow this object to 542 // set. A proper fix would provide a mechanism to allow this object to
538 // refresh the MediaPlayer's LocalFrame and FrameLoader references on document 543 // refresh the MediaPlayer's LocalFrame and FrameLoader references on document
539 // changes so that playback can be resumed properly. 544 // changes so that playback can be resumed properly.
540 m_ignorePreloadNone = false; 545 m_ignorePreloadNone = false;
(...skipping 823 matching lines...) Expand 10 before | Expand all | Expand 10 after
1364 // didPassCORSAccessCheck() means it was a successful CORS-enabled fetch 1369 // didPassCORSAccessCheck() means it was a successful CORS-enabled fetch
1365 // (vs. non-CORS-enabled or failed). 1370 // (vs. non-CORS-enabled or failed).
1366 // taintsCanvas() does checkAccess() on the URL plus allow data sources, 1371 // taintsCanvas() does checkAccess() on the URL plus allow data sources,
1367 // to ensure that it is not a URL that requires CORS (basically same 1372 // to ensure that it is not a URL that requires CORS (basically same
1368 // origin). 1373 // origin).
1369 return hasSingleSecurityOrigin() && 1374 return hasSingleSecurityOrigin() &&
1370 ((webMediaPlayer() && webMediaPlayer()->didPassCORSAccessCheck()) || 1375 ((webMediaPlayer() && webMediaPlayer()->didPassCORSAccessCheck()) ||
1371 !origin->taintsCanvas(currentSrc())); 1376 !origin->taintsCanvas(currentSrc()));
1372 } 1377 }
1373 1378
1379 bool HTMLMediaElement::isCrossOrigin() const {
1380 return isDocumentCrossOrigin(document());
1381 }
1382
1374 void HTMLMediaElement::startProgressEventTimer() { 1383 void HTMLMediaElement::startProgressEventTimer() {
1375 if (m_progressEventTimer.isActive()) 1384 if (m_progressEventTimer.isActive())
1376 return; 1385 return;
1377 1386
1378 m_previousProgressTime = WTF::currentTime(); 1387 m_previousProgressTime = WTF::currentTime();
1379 // 350ms is not magic, it is in the spec! 1388 // 350ms is not magic, it is in the spec!
1380 m_progressEventTimer.startRepeating(0.350, BLINK_FROM_HERE); 1389 m_progressEventTimer.startRepeating(0.350, BLINK_FROM_HERE);
1381 } 1390 }
1382 1391
1383 void HTMLMediaElement::waitForSourceChange() { 1392 void HTMLMediaElement::waitForSourceChange() {
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after
1729 1738
1730 // Check for autoplay, and record metrics about it if needed. 1739 // Check for autoplay, and record metrics about it if needed.
1731 if (shouldAutoplay(RecordMetricsBehavior::DoRecord)) { 1740 if (shouldAutoplay(RecordMetricsBehavior::DoRecord)) {
1732 m_autoplayUmaHelper->onAutoplayInitiated(AutoplaySource::Attribute); 1741 m_autoplayUmaHelper->onAutoplayInitiated(AutoplaySource::Attribute);
1733 1742
1734 // If the autoplay experiment says that it's okay to play now, 1743 // If the autoplay experiment says that it's okay to play now,
1735 // then don't require a user gesture. 1744 // then don't require a user gesture.
1736 m_autoplayHelper->becameReadyToPlay(); 1745 m_autoplayHelper->becameReadyToPlay();
1737 1746
1738 if (!isGestureNeededForPlayback()) { 1747 if (!isGestureNeededForPlayback()) {
1748 if (isGestureNeededForPlaybackIfCrossOriginExperimentEnabled()) {
1749 m_autoplayUmaHelper->recordCrossOriginExperimentMetric(
1750 AutoplayCrossOriginExperimentMetric::AutoplayBlocked);
1751 } else {
1752 m_autoplayUmaHelper->recordCrossOriginExperimentMetric(
1753 AutoplayCrossOriginExperimentMetric::AutoplayAllowed);
1754 }
1739 if (isHTMLVideoElement() && muted() && 1755 if (isHTMLVideoElement() && muted() &&
1740 RuntimeEnabledFeatures::autoplayMutedVideosEnabled()) { 1756 RuntimeEnabledFeatures::autoplayMutedVideosEnabled()) {
1741 // We might end up in a situation where the previous 1757 // We might end up in a situation where the previous
1742 // observer didn't had time to fire yet. We can avoid 1758 // observer didn't had time to fire yet. We can avoid
1743 // creating a new one in this case. 1759 // creating a new one in this case.
1744 if (!m_autoplayVisibilityObserver) { 1760 if (!m_autoplayVisibilityObserver) {
1745 m_autoplayVisibilityObserver = new ElementVisibilityObserver( 1761 m_autoplayVisibilityObserver = new ElementVisibilityObserver(
1746 this, 1762 this,
1747 WTF::bind(&HTMLMediaElement::onVisibilityChangedForAutoplay, 1763 WTF::bind(&HTMLMediaElement::onVisibilityChangedForAutoplay,
1748 wrapWeakPersistent(this))); 1764 wrapWeakPersistent(this)));
1749 m_autoplayVisibilityObserver->start(); 1765 m_autoplayVisibilityObserver->start();
1750 } 1766 }
1751 } else { 1767 } else {
1752 m_paused = false; 1768 m_paused = false;
1753 scheduleEvent(EventTypeNames::play); 1769 scheduleEvent(EventTypeNames::play);
1754 scheduleNotifyPlaying(); 1770 scheduleNotifyPlaying();
1755 m_autoplaying = false; 1771 m_autoplaying = false;
1756 } 1772 }
1773 } else {
1774 m_autoplayUmaHelper->recordCrossOriginExperimentMetric(
1775 AutoplayCrossOriginExperimentMetric::AutoplayBlocked);
1757 } 1776 }
1758 } 1777 }
1759 1778
1760 scheduleEvent(EventTypeNames::canplaythrough); 1779 scheduleEvent(EventTypeNames::canplaythrough);
1761 1780
1762 shouldUpdateDisplayState = true; 1781 shouldUpdateDisplayState = true;
1763 } 1782 }
1764 1783
1765 if (shouldUpdateDisplayState) { 1784 if (shouldUpdateDisplayState) {
1766 updateDisplayState(); 1785 updateDisplayState();
(...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after
2239 if (m_autoplayHelper->isPlaybackDeferred()) 2258 if (m_autoplayHelper->isPlaybackDeferred())
2240 return nullptr; 2259 return nullptr;
2241 2260
2242 // If we're already playing, then this play would do nothing anyway. 2261 // If we're already playing, then this play would do nothing anyway.
2243 // Call playInternal to handle scheduling the promise resolution. 2262 // Call playInternal to handle scheduling the promise resolution.
2244 if (!m_paused) { 2263 if (!m_paused) {
2245 playInternal(); 2264 playInternal();
2246 return nullptr; 2265 return nullptr;
2247 } 2266 }
2248 2267
2268 m_autoplayUmaHelper->recordCrossOriginExperimentMetric(
2269 AutoplayCrossOriginExperimentMetric::AutoplayBlocked);
2249 recordAutoplayMetric(PlayMethodFailed); 2270 recordAutoplayMetric(PlayMethodFailed);
2250 String message = ExceptionMessages::failedToExecute( 2271 String message = ExceptionMessages::failedToExecute(
2251 "play", "HTMLMediaElement", 2272 "play", "HTMLMediaElement",
2252 "API can only be initiated by a user gesture."); 2273 "API can only be initiated by a user gesture.");
2253 document().addConsoleMessage(ConsoleMessage::create( 2274 document().addConsoleMessage(ConsoleMessage::create(
2254 JSMessageSource, WarningMessageLevel, message)); 2275 JSMessageSource, WarningMessageLevel, message));
2255 return NotAllowedError; 2276 return NotAllowedError;
2277 } else {
2278 if (isGestureNeededForPlaybackIfCrossOriginExperimentEnabled()) {
2279 m_autoplayUmaHelper->recordCrossOriginExperimentMetric(
2280 AutoplayCrossOriginExperimentMetric::AutoplayBlocked);
2281 } else {
2282 m_autoplayUmaHelper->recordCrossOriginExperimentMetric(
whywhat 2016/11/29 21:42:04 seems like we'll record some metrics when the expe
Zhiqiang Zhang (Slow) 2016/11/30 17:30:52 Yes :) Since the experiment might break many sites
2283 AutoplayCrossOriginExperimentMetric::AutoplayAllowed);
2284 }
2256 } 2285 }
2257 } else { 2286 } else {
2287 m_autoplayUmaHelper->recordCrossOriginExperimentMetric(
2288 AutoplayCrossOriginExperimentMetric::PlayedWithGesture);
2258 UserGestureIndicator::utilizeUserGesture(); 2289 UserGestureIndicator::utilizeUserGesture();
2259 // We ask the helper to remove the gesture requirement for us, so that 2290 // We ask the helper to remove the gesture requirement for us, so that
2260 // it can record the reason. 2291 // it can record the reason.
2261 m_autoplayHelper->unlockUserGesture(GesturelessPlaybackEnabledByPlayMethod); 2292 m_autoplayHelper->unlockUserGesture(GesturelessPlaybackEnabledByPlayMethod);
2262 } 2293 }
2263 2294
2264 if (m_error && m_error->code() == MediaError::kMediaErrSrcNotSupported) 2295 if (m_error && m_error->code() == MediaError::kMediaErrSrcNotSupported)
2265 return NotSupportedError; 2296 return NotSupportedError;
2266 2297
2267 playInternal(); 2298 playInternal();
(...skipping 1629 matching lines...) Expand 10 before | Expand all | Expand 10 after
3897 3928
3898 return document.settings()->mediaPlaybackRequiresUserGesture(); 3929 return document.settings()->mediaPlaybackRequiresUserGesture();
3899 } 3930 }
3900 3931
3901 bool HTMLMediaElement::isLockedPendingUserGesture() const { 3932 bool HTMLMediaElement::isLockedPendingUserGesture() const {
3902 return m_lockedPendingUserGesture; 3933 return m_lockedPendingUserGesture;
3903 } 3934 }
3904 3935
3905 void HTMLMediaElement::unlockUserGesture() { 3936 void HTMLMediaElement::unlockUserGesture() {
3906 m_lockedPendingUserGesture = false; 3937 m_lockedPendingUserGesture = false;
3938 m_lockedPendingUserGestureIfCrossOriginExperimentEnabled = false;
3907 } 3939 }
3908 3940
3909 bool HTMLMediaElement::isGestureNeededForPlayback() const { 3941 bool HTMLMediaElement::isGestureNeededForPlayback() const {
3910 if (!m_lockedPendingUserGesture) 3942 if (!m_lockedPendingUserGesture)
3911 return false; 3943 return false;
3912 3944
3913 if (loadType() == WebMediaPlayer::LoadTypeMediaStream) 3945 if (loadType() == WebMediaPlayer::LoadTypeMediaStream)
3914 return false; 3946 return false;
3915 3947
3916 // We want to allow muted video to autoplay if: 3948 // We want to allow muted video to autoplay if:
3917 // - the flag is enabled; 3949 // - the flag is enabled;
3918 // - Data Saver is not enabled; 3950 // - Data Saver is not enabled;
3919 // - Preload was not disabled (low end devices); 3951 // - Preload was not disabled (low end devices);
3920 // - Autoplay is enabled in settings; 3952 // - Autoplay is enabled in settings;
3921 if (isHTMLVideoElement() && muted() && 3953 if (isHTMLVideoElement() && muted() &&
3922 RuntimeEnabledFeatures::autoplayMutedVideosEnabled() && 3954 RuntimeEnabledFeatures::autoplayMutedVideosEnabled() &&
3923 !(document().settings() && document().settings()->dataSaverEnabled()) && 3955 !(document().settings() && document().settings()->dataSaverEnabled()) &&
3924 !(document().settings() && 3956 !(document().settings() &&
3925 document().settings()->forcePreloadNoneForMediaElements()) && 3957 document().settings()->forcePreloadNoneForMediaElements()) &&
3926 isAutoplayAllowedPerSettings()) { 3958 isAutoplayAllowedPerSettings()) {
3927 return false; 3959 return false;
3928 } 3960 }
3929 3961
3930 if (m_autoplayHelper->isGestureRequirementOverridden()) 3962 if (m_autoplayHelper->isGestureRequirementOverridden())
3931 return false; 3963 return false;
3932 3964
3933 return true; 3965 return true;
3934 } 3966 }
3935 3967
3968 bool HTMLMediaElement::
whywhat 2016/11/29 21:42:04 how is this different from the isGestureNeededForP
Zhiqiang Zhang (Slow) 2016/11/30 17:30:52 Done. Added the missing checks.
3969 isGestureNeededForPlaybackIfCrossOriginExperimentEnabled() const {
3970 if (!m_lockedPendingUserGestureIfCrossOriginExperimentEnabled)
3971 return false;
3972
3973 if (isHTMLVideoElement() && muted() &&
3974 RuntimeEnabledFeatures::autoplayMutedVideosEnabled() &&
3975 !(document().settings() && document().settings()->dataSaverEnabled()) &&
3976 !(document().settings() &&
3977 document().settings()->forcePreloadNoneForMediaElements()) &&
3978 isAutoplayAllowedPerSettings()) {
3979 return false;
3980 }
3981
3982 return true;
3983 }
3984
3936 bool HTMLMediaElement::isAutoplayAllowedPerSettings() const { 3985 bool HTMLMediaElement::isAutoplayAllowedPerSettings() const {
3937 LocalFrame* frame = document().frame(); 3986 LocalFrame* frame = document().frame();
3938 if (!frame) 3987 if (!frame)
3939 return false; 3988 return false;
3940 FrameLoaderClient* frameLoaderClient = frame->loader().client(); 3989 FrameLoaderClient* frameLoaderClient = frame->loader().client();
3941 return frameLoaderClient && frameLoaderClient->allowAutoplay(false); 3990 return frameLoaderClient && frameLoaderClient->allowAutoplay(false);
3942 } 3991 }
3943 3992
3944 void HTMLMediaElement::setNetworkState(NetworkState state) { 3993 void HTMLMediaElement::setNetworkState(NetworkState state) {
3945 if (m_networkState != state) { 3994 if (m_networkState != state) {
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
4207 4256
4208 IntRect HTMLMediaElement::AutoplayHelperClientImpl::absoluteBoundingBoxRect() 4257 IntRect HTMLMediaElement::AutoplayHelperClientImpl::absoluteBoundingBoxRect()
4209 const { 4258 const {
4210 IntRect result; 4259 IntRect result;
4211 if (LayoutObject* object = m_element->layoutObject()) 4260 if (LayoutObject* object = m_element->layoutObject())
4212 result = object->absoluteBoundingBoxRect(); 4261 result = object->absoluteBoundingBoxRect();
4213 return result; 4262 return result;
4214 } 4263 }
4215 4264
4216 } // namespace blink 4265 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698