Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 279 case WebMediaPlayer::PreloadAuto: | 279 case WebMediaPlayer::PreloadAuto: |
| 280 return "auto"; | 280 return "auto"; |
| 281 } | 281 } |
| 282 | 282 |
| 283 NOTREACHED(); | 283 NOTREACHED(); |
| 284 return String(); | 284 return String(); |
| 285 } | 285 } |
| 286 | 286 |
| 287 } // anonymous namespace | 287 } // anonymous namespace |
| 288 | 288 |
| 289 class HTMLMediaElement::AutoplayHelperClientImpl | |
| 290 : public AutoplayExperimentHelper::Client { | |
| 291 public: | |
| 292 static AutoplayHelperClientImpl* create(HTMLMediaElement* element) { | |
| 293 return new AutoplayHelperClientImpl(element); | |
| 294 } | |
| 295 | |
| 296 virtual ~AutoplayHelperClientImpl(); | |
| 297 | |
| 298 using RecordMetricsBehavior = HTMLMediaElement::RecordMetricsBehavior; | |
| 299 | |
| 300 double currentTime() const override { return m_element->currentTime(); } | |
| 301 double duration() const override { return m_element->duration(); } | |
| 302 bool paused() const override { return m_element->paused(); } | |
| 303 bool ended() const override { return m_element->ended(); } | |
| 304 bool muted() const override { return m_element->muted(); } | |
| 305 void setMuted(bool muted) override { m_element->setMuted(muted); } | |
| 306 void playInternal() override { m_element->playInternal(); } | |
| 307 void pauseInternal() override { m_element->pauseInternal(); } | |
| 308 bool isLockedPendingUserGesture() const override { | |
| 309 return m_element->isLockedPendingUserGesture(); | |
| 310 } | |
| 311 void unlockUserGesture() override { m_element->unlockUserGesture(); } | |
| 312 void recordAutoplayMetric(AutoplayMetrics metric) override { | |
| 313 m_element->recordAutoplayMetric(metric); | |
| 314 } | |
| 315 bool shouldAutoplay() override { | |
| 316 return m_element->shouldAutoplay(RecordMetricsBehavior::DoNotRecord); | |
| 317 } | |
| 318 bool isHTMLVideoElement() const override { | |
| 319 return m_element->isHTMLVideoElement(); | |
| 320 } | |
| 321 bool isHTMLAudioElement() const override { | |
| 322 return m_element->isHTMLAudioElement(); | |
| 323 } | |
| 324 | |
| 325 // Document | |
| 326 bool isLegacyViewportType() override; | |
| 327 PageVisibilityState pageVisibilityState() const override; | |
| 328 String autoplayExperimentMode() const override; | |
| 329 | |
| 330 // Frame | |
| 331 bool isCrossOrigin() const override { | |
| 332 const LocalFrame* frame = m_element->document().frame(); | |
| 333 return frame && frame->isCrossOriginSubframe(); | |
| 334 } | |
| 335 | |
| 336 bool isAutoplayAllowedPerSettings() const override; | |
| 337 | |
| 338 // LayoutObject | |
| 339 void setRequestPositionUpdates(bool) override; | |
| 340 IntRect absoluteBoundingBoxRect() const override; | |
| 341 | |
| 342 DEFINE_INLINE_VIRTUAL_TRACE() { | |
| 343 visitor->trace(m_element); | |
| 344 Client::trace(visitor); | |
| 345 } | |
| 346 | |
| 347 private: | |
| 348 AutoplayHelperClientImpl(HTMLMediaElement* element) : m_element(element) {} | |
| 349 | |
| 350 Member<HTMLMediaElement> m_element; | |
| 351 }; | |
| 352 | |
| 353 void HTMLMediaElement::recordAutoplayMetric(AutoplayMetrics metric) { | |
| 354 DEFINE_STATIC_LOCAL(EnumerationHistogram, autoplayHistogram, | |
| 355 ("Blink.MediaElement.Autoplay", NumberOfAutoplayMetrics)); | |
| 356 autoplayHistogram.count(metric); | |
| 357 } | |
| 358 | |
| 359 MIMETypeRegistry::SupportsType HTMLMediaElement::supportsType( | 289 MIMETypeRegistry::SupportsType HTMLMediaElement::supportsType( |
| 360 const ContentType& contentType) { | 290 const ContentType& contentType) { |
| 361 DEFINE_STATIC_LOCAL(const String, codecs, ("codecs")); | 291 DEFINE_STATIC_LOCAL(const String, codecs, ("codecs")); |
| 362 | 292 |
| 363 String type = contentType.type().lower(); | 293 String type = contentType.type().lower(); |
| 364 // The codecs string is not lower-cased because MP4 values are case sensitive | 294 // The codecs string is not lower-cased because MP4 values are case sensitive |
| 365 // per http://tools.ietf.org/html/rfc4281#page-7. | 295 // per http://tools.ietf.org/html/rfc4281#page-7. |
| 366 String typeCodecs = contentType.parameter(codecs); | 296 String typeCodecs = contentType.parameter(codecs); |
| 367 | 297 |
| 368 if (type.isEmpty()) | 298 if (type.isEmpty()) |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 445 m_textTracksVisible(false), | 375 m_textTracksVisible(false), |
| 446 m_shouldPerformAutomaticTrackSelection(true), | 376 m_shouldPerformAutomaticTrackSelection(true), |
| 447 m_tracksAreReady(true), | 377 m_tracksAreReady(true), |
| 448 m_processingPreferenceChange(false), | 378 m_processingPreferenceChange(false), |
| 449 m_playingRemotely(false), | 379 m_playingRemotely(false), |
| 450 m_inOverlayFullscreenVideo(false), | 380 m_inOverlayFullscreenVideo(false), |
| 451 m_audioTracks(this, AudioTrackList::create(*this)), | 381 m_audioTracks(this, AudioTrackList::create(*this)), |
| 452 m_videoTracks(this, VideoTrackList::create(*this)), | 382 m_videoTracks(this, VideoTrackList::create(*this)), |
| 453 m_textTracks(this, nullptr), | 383 m_textTracks(this, nullptr), |
| 454 m_audioSourceNode(nullptr), | 384 m_audioSourceNode(nullptr), |
| 455 m_autoplayHelperClient(AutoplayHelperClientImpl::create(this)), | |
| 456 m_autoplayHelper( | |
| 457 AutoplayExperimentHelper::create(m_autoplayHelperClient.get())), | |
| 458 m_autoplayUmaHelper(AutoplayUmaHelper::create(this)), | 385 m_autoplayUmaHelper(AutoplayUmaHelper::create(this)), |
| 459 m_remotePlaybackClient(nullptr), | 386 m_remotePlaybackClient(nullptr), |
| 460 m_autoplayVisibilityObserver(nullptr) { | 387 m_autoplayVisibilityObserver(nullptr) { |
| 461 ThreadState::current()->registerPreFinalizer(this); | 388 ThreadState::current()->registerPreFinalizer(this); |
| 462 | 389 |
| 463 BLINK_MEDIA_LOG << "HTMLMediaElement(" << (void*)this << ")"; | 390 BLINK_MEDIA_LOG << "HTMLMediaElement(" << (void*)this << ")"; |
| 464 | 391 |
| 465 // If any experiment is enabled, then we want to enable a user gesture by | 392 // If any experiment is enabled, then we want to enable a user gesture by |
| 466 // default, otherwise the experiment does nothing. | 393 // default, otherwise the experiment does nothing. |
| 467 if ((document.settings() && | 394 if ((document.settings() && |
| 468 document.settings()->mediaPlaybackRequiresUserGesture()) || | 395 document.settings()->mediaPlaybackRequiresUserGesture())) { |
| 469 m_autoplayHelper->isExperimentEnabled()) { | |
| 470 m_lockedPendingUserGesture = true; | 396 m_lockedPendingUserGesture = true; |
| 471 } | 397 } |
| 472 | 398 |
| 473 LocalFrame* frame = document.frame(); | 399 LocalFrame* frame = document.frame(); |
| 474 if (frame) { | 400 if (frame) { |
| 475 m_remotePlaybackClient = | 401 m_remotePlaybackClient = |
| 476 frame->loader().client()->createWebRemotePlaybackClient(*this); | 402 frame->loader().client()->createWebRemotePlaybackClient(*this); |
| 477 } | 403 } |
| 478 | 404 |
| 479 setHasCustomStyleCallbacks(); | 405 setHasCustomStyleCallbacks(); |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 506 } | 432 } |
| 507 | 433 |
| 508 void HTMLMediaElement::didMoveToNewDocument(Document& oldDocument) { | 434 void HTMLMediaElement::didMoveToNewDocument(Document& oldDocument) { |
| 509 BLINK_MEDIA_LOG << "didMoveToNewDocument(" << (void*)this << ")"; | 435 BLINK_MEDIA_LOG << "didMoveToNewDocument(" << (void*)this << ")"; |
| 510 | 436 |
| 511 m_autoplayUmaHelper->didMoveToNewDocument(oldDocument); | 437 m_autoplayUmaHelper->didMoveToNewDocument(oldDocument); |
| 512 // If any experiment is enabled, then we want to enable a user gesture by | 438 // If any experiment is enabled, then we want to enable a user gesture by |
| 513 // default, otherwise the experiment does nothing. | 439 // default, otherwise the experiment does nothing. |
| 514 bool oldDocumentRequiresUserGesture = | 440 bool oldDocumentRequiresUserGesture = |
| 515 (oldDocument.settings() && | 441 (oldDocument.settings() && |
| 516 oldDocument.settings()->mediaPlaybackRequiresUserGesture()) || | 442 oldDocument.settings()->mediaPlaybackRequiresUserGesture()); |
| 517 m_autoplayHelper->isExperimentEnabled(); | |
| 518 bool newDocumentRequiresUserGesture = | 443 bool newDocumentRequiresUserGesture = |
| 519 (document().settings() && | 444 (document().settings() && |
| 520 document().settings()->mediaPlaybackRequiresUserGesture()) || | 445 document().settings()->mediaPlaybackRequiresUserGesture()); |
| 521 m_autoplayHelper->isExperimentEnabled(); | |
| 522 if (newDocumentRequiresUserGesture && !oldDocumentRequiresUserGesture) { | 446 if (newDocumentRequiresUserGesture && !oldDocumentRequiresUserGesture) { |
| 523 m_lockedPendingUserGesture = true; | 447 m_lockedPendingUserGesture = true; |
| 524 } | 448 } |
| 525 | 449 |
| 526 if (m_shouldDelayLoadEvent) { | 450 if (m_shouldDelayLoadEvent) { |
| 527 document().incrementLoadEventDelayCount(); | 451 document().incrementLoadEventDelayCount(); |
| 528 // Note: Keeping the load event delay count increment on oldDocument that | 452 // Note: Keeping the load event delay count increment on oldDocument that |
| 529 // was added when m_shouldDelayLoadEvent was set so that destruction of | 453 // was added when m_shouldDelayLoadEvent was set so that destruction of |
| 530 // m_webMediaPlayer can not cause load event dispatching in oldDocument. | 454 // m_webMediaPlayer can not cause load event dispatching in oldDocument. |
| 531 } else { | 455 } else { |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 741 | 665 |
| 742 BLINK_MEDIA_LOG << "canPlayType(" << (void*)this << ", " << mimeType | 666 BLINK_MEDIA_LOG << "canPlayType(" << (void*)this << ", " << mimeType |
| 743 << ") -> " << canPlay; | 667 << ") -> " << canPlay; |
| 744 | 668 |
| 745 return canPlay; | 669 return canPlay; |
| 746 } | 670 } |
| 747 | 671 |
| 748 void HTMLMediaElement::load() { | 672 void HTMLMediaElement::load() { |
| 749 BLINK_MEDIA_LOG << "load(" << (void*)this << ")"; | 673 BLINK_MEDIA_LOG << "load(" << (void*)this << ")"; |
| 750 | 674 |
| 751 m_autoplayHelper->loadMethodCalled(); | 675 if (isLockedPendingUserGesture() && |
| 676 UserGestureIndicator::utilizeUserGesture()) { | |
|
foolip
2016/11/23 12:40:55
This isn't what I had expected, but https://codere
Zhiqiang Zhang (Slow)
2016/11/23 17:18:28
This logic was flattened from AutoplayExperimental
foolip
2016/11/23 19:15:55
Originally it was processingUserGesture(), so that
| |
| 677 unlockUserGesture(); | |
| 678 } | |
| 752 | 679 |
| 753 m_ignorePreloadNone = true; | 680 m_ignorePreloadNone = true; |
| 754 invokeLoadAlgorithm(); | 681 invokeLoadAlgorithm(); |
| 755 } | 682 } |
| 756 | 683 |
| 757 // TODO(srirama.m): Currently m_ignorePreloadNone is reset before calling | 684 // TODO(srirama.m): Currently m_ignorePreloadNone is reset before calling |
| 758 // invokeLoadAlgorithm() in all places except load(). Move it inside here | 685 // invokeLoadAlgorithm() in all places except load(). Move it inside here |
| 759 // once microtask is implemented for "Await a stable state" step | 686 // once microtask is implemented for "Await a stable state" step |
| 760 // in resource selection algorithm. | 687 // in resource selection algorithm. |
| 761 void HTMLMediaElement::invokeLoadAlgorithm() { | 688 void HTMLMediaElement::invokeLoadAlgorithm() { |
| (...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1062 | 989 |
| 1063 LocalFrame* frame = document().frame(); | 990 LocalFrame* frame = document().frame(); |
| 1064 if (!frame) { | 991 if (!frame) { |
| 1065 mediaLoadingFailed(WebMediaPlayer::NetworkStateFormatError); | 992 mediaLoadingFailed(WebMediaPlayer::NetworkStateFormatError); |
| 1066 return; | 993 return; |
| 1067 } | 994 } |
| 1068 | 995 |
| 1069 // The resource fetch algorithm | 996 // The resource fetch algorithm |
| 1070 setNetworkState(kNetworkLoading); | 997 setNetworkState(kNetworkLoading); |
| 1071 | 998 |
| 1072 m_autoplayHelper->loadingStarted(); | |
| 1073 | |
| 1074 // Set m_currentSrc *before* changing to the cache url, the fact that we are | 999 // Set m_currentSrc *before* changing to the cache url, the fact that we are |
| 1075 // loading from the app cache is an internal detail not exposed through the | 1000 // loading from the app cache is an internal detail not exposed through the |
| 1076 // media element API. | 1001 // media element API. |
| 1077 m_currentSrc = url; | 1002 m_currentSrc = url; |
| 1078 | 1003 |
| 1079 if (m_audioSourceNode) | 1004 if (m_audioSourceNode) |
| 1080 m_audioSourceNode->onCurrentSrcChanged(m_currentSrc); | 1005 m_audioSourceNode->onCurrentSrcChanged(m_currentSrc); |
| 1081 | 1006 |
| 1082 BLINK_MEDIA_LOG << "loadResource(" << (void*)this << ") - m_currentSrc -> " | 1007 BLINK_MEDIA_LOG << "loadResource(" << (void*)this << ") - m_currentSrc -> " |
| 1083 << urlForLoggingMedia(m_currentSrc); | 1008 << urlForLoggingMedia(m_currentSrc); |
| (...skipping 646 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1730 if (oldState <= kHaveCurrentData) { | 1655 if (oldState <= kHaveCurrentData) { |
| 1731 scheduleEvent(EventTypeNames::canplay); | 1656 scheduleEvent(EventTypeNames::canplay); |
| 1732 if (isPotentiallyPlaying) | 1657 if (isPotentiallyPlaying) |
| 1733 scheduleNotifyPlaying(); | 1658 scheduleNotifyPlaying(); |
| 1734 } | 1659 } |
| 1735 | 1660 |
| 1736 // Check for autoplay, and record metrics about it if needed. | 1661 // Check for autoplay, and record metrics about it if needed. |
| 1737 if (shouldAutoplay(RecordMetricsBehavior::DoRecord)) { | 1662 if (shouldAutoplay(RecordMetricsBehavior::DoRecord)) { |
| 1738 m_autoplayUmaHelper->onAutoplayInitiated(AutoplaySource::Attribute); | 1663 m_autoplayUmaHelper->onAutoplayInitiated(AutoplaySource::Attribute); |
| 1739 | 1664 |
| 1740 // If the autoplay experiment says that it's okay to play now, | |
| 1741 // then don't require a user gesture. | |
| 1742 m_autoplayHelper->becameReadyToPlay(); | |
| 1743 | |
| 1744 if (!isGestureNeededForPlayback()) { | 1665 if (!isGestureNeededForPlayback()) { |
| 1745 if (isHTMLVideoElement() && muted() && | 1666 if (isHTMLVideoElement() && muted() && |
| 1746 RuntimeEnabledFeatures::autoplayMutedVideosEnabled()) { | 1667 RuntimeEnabledFeatures::autoplayMutedVideosEnabled()) { |
| 1747 // We might end up in a situation where the previous | 1668 // We might end up in a situation where the previous |
| 1748 // observer didn't had time to fire yet. We can avoid | 1669 // observer didn't had time to fire yet. We can avoid |
| 1749 // creating a new one in this case. | 1670 // creating a new one in this case. |
| 1750 if (!m_autoplayVisibilityObserver) { | 1671 if (!m_autoplayVisibilityObserver) { |
| 1751 m_autoplayVisibilityObserver = new ElementVisibilityObserver( | 1672 m_autoplayVisibilityObserver = new ElementVisibilityObserver( |
| 1752 this, | 1673 this, |
| 1753 WTF::bind(&HTMLMediaElement::onVisibilityChangedForAutoplay, | 1674 WTF::bind(&HTMLMediaElement::onVisibilityChangedForAutoplay, |
| (...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2108 // The ended attribute must return true if the media element has ended | 2029 // The ended attribute must return true if the media element has ended |
| 2109 // playback and the direction of playback is forwards, and false otherwise. | 2030 // playback and the direction of playback is forwards, and false otherwise. |
| 2110 return endedPlayback() && getDirectionOfPlayback() == Forward; | 2031 return endedPlayback() && getDirectionOfPlayback() == Forward; |
| 2111 } | 2032 } |
| 2112 | 2033 |
| 2113 bool HTMLMediaElement::autoplay() const { | 2034 bool HTMLMediaElement::autoplay() const { |
| 2114 return fastHasAttribute(autoplayAttr); | 2035 return fastHasAttribute(autoplayAttr); |
| 2115 } | 2036 } |
| 2116 | 2037 |
| 2117 bool HTMLMediaElement::shouldAutoplay( | 2038 bool HTMLMediaElement::shouldAutoplay( |
| 2118 const RecordMetricsBehavior recordMetrics) { | 2039 const RecordMetricsBehavior recordMetrics) { |
|
foolip
2016/11/23 12:40:55
Remove the now unused argument.
Zhiqiang Zhang (Slow)
2016/11/23 18:27:34
Done.
| |
| 2119 if (m_autoplaying && m_paused && autoplay()) { | 2040 if (m_autoplaying && m_paused && autoplay()) { |
|
foolip
2016/11/23 12:40:55
This now ends up looking a bit silly and not trivi
Zhiqiang Zhang (Slow)
2016/11/23 18:27:34
Done.
| |
| 2120 if (document().isSandboxed(SandboxAutomaticFeatures)) { | 2041 if (document().isSandboxed(SandboxAutomaticFeatures)) |
| 2121 if (recordMetrics == RecordMetricsBehavior::DoRecord) | |
| 2122 m_autoplayHelper->recordSandboxFailure(); | |
| 2123 return false; | 2042 return false; |
| 2124 } | |
| 2125 | |
| 2126 return true; | 2043 return true; |
| 2127 } | 2044 } |
| 2128 | 2045 |
| 2129 return false; | 2046 return false; |
| 2130 } | 2047 } |
| 2131 | 2048 |
| 2132 String HTMLMediaElement::preload() const { | 2049 String HTMLMediaElement::preload() const { |
| 2133 return preloadTypeToString(preloadType()); | 2050 return preloadTypeToString(preloadType()); |
| 2134 } | 2051 } |
| 2135 | 2052 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2228 resolver->reject(DOMException::create(code.get(), message)); | 2145 resolver->reject(DOMException::create(code.get(), message)); |
| 2229 return promise; | 2146 return promise; |
| 2230 } | 2147 } |
| 2231 | 2148 |
| 2232 return promise; | 2149 return promise; |
| 2233 } | 2150 } |
| 2234 | 2151 |
| 2235 Nullable<ExceptionCode> HTMLMediaElement::play() { | 2152 Nullable<ExceptionCode> HTMLMediaElement::play() { |
| 2236 BLINK_MEDIA_LOG << "play(" << (void*)this << ")"; | 2153 BLINK_MEDIA_LOG << "play(" << (void*)this << ")"; |
| 2237 | 2154 |
| 2238 m_autoplayHelper->playMethodCalled(); | |
| 2239 | |
| 2240 if (!UserGestureIndicator::processingUserGesture()) { | 2155 if (!UserGestureIndicator::processingUserGesture()) { |
| 2241 m_autoplayUmaHelper->onAutoplayInitiated(AutoplaySource::Method); | 2156 m_autoplayUmaHelper->onAutoplayInitiated(AutoplaySource::Method); |
| 2242 if (isGestureNeededForPlayback()) { | 2157 if (isGestureNeededForPlayback()) { |
| 2243 // If playback is deferred, then don't start playback but don't | |
| 2244 // fail yet either. | |
| 2245 if (m_autoplayHelper->isPlaybackDeferred()) | |
| 2246 return nullptr; | |
| 2247 | |
| 2248 // If we're already playing, then this play would do nothing anyway. | 2158 // If we're already playing, then this play would do nothing anyway. |
| 2249 // Call playInternal to handle scheduling the promise resolution. | 2159 // Call playInternal to handle scheduling the promise resolution. |
| 2250 if (!m_paused) { | 2160 if (!m_paused) { |
| 2251 playInternal(); | 2161 playInternal(); |
| 2252 return nullptr; | 2162 return nullptr; |
| 2253 } | 2163 } |
| 2254 | 2164 |
| 2255 recordAutoplayMetric(PlayMethodFailed); | |
| 2256 String message = ExceptionMessages::failedToExecute( | 2165 String message = ExceptionMessages::failedToExecute( |
| 2257 "play", "HTMLMediaElement", | 2166 "play", "HTMLMediaElement", |
| 2258 "API can only be initiated by a user gesture."); | 2167 "API can only be initiated by a user gesture."); |
| 2259 document().addConsoleMessage(ConsoleMessage::create( | 2168 document().addConsoleMessage(ConsoleMessage::create( |
| 2260 JSMessageSource, WarningMessageLevel, message)); | 2169 JSMessageSource, WarningMessageLevel, message)); |
| 2261 return NotAllowedError; | 2170 return NotAllowedError; |
| 2262 } | 2171 } |
| 2263 } else { | 2172 } else { |
| 2264 UserGestureIndicator::utilizeUserGesture(); | 2173 UserGestureIndicator::utilizeUserGesture(); |
|
foolip
2016/11/23 12:40:55
Optional nit: hoist utilizeUserGesture() to above.
Zhiqiang Zhang (Slow)
2016/11/23 18:27:34
Did you mean to move it to utilizeUserGesture() to
foolip
2016/11/23 19:15:55
Will do, but will base it on your CL since it's go
| |
| 2265 // We ask the helper to remove the gesture requirement for us, so that | 2174 unlockUserGesture(); |
| 2266 // it can record the reason. | |
| 2267 m_autoplayHelper->unlockUserGesture(GesturelessPlaybackEnabledByPlayMethod); | |
| 2268 } | 2175 } |
| 2269 | 2176 |
| 2270 if (m_error && m_error->code() == MediaError::kMediaErrSrcNotSupported) | 2177 if (m_error && m_error->code() == MediaError::kMediaErrSrcNotSupported) |
| 2271 return NotSupportedError; | 2178 return NotSupportedError; |
| 2272 | 2179 |
| 2273 playInternal(); | 2180 playInternal(); |
| 2274 | 2181 |
| 2275 return nullptr; | 2182 return nullptr; |
| 2276 } | 2183 } |
| 2277 | 2184 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2324 | 2231 |
| 2325 pauseInternal(); | 2232 pauseInternal(); |
| 2326 } | 2233 } |
| 2327 | 2234 |
| 2328 void HTMLMediaElement::pauseInternal() { | 2235 void HTMLMediaElement::pauseInternal() { |
| 2329 BLINK_MEDIA_LOG << "pauseInternal(" << (void*)this << ")"; | 2236 BLINK_MEDIA_LOG << "pauseInternal(" << (void*)this << ")"; |
| 2330 | 2237 |
| 2331 if (m_networkState == kNetworkEmpty) | 2238 if (m_networkState == kNetworkEmpty) |
| 2332 invokeResourceSelectionAlgorithm(); | 2239 invokeResourceSelectionAlgorithm(); |
| 2333 | 2240 |
| 2334 m_autoplayHelper->pauseMethodCalled(); | |
| 2335 | |
| 2336 m_autoplaying = false; | 2241 m_autoplaying = false; |
| 2337 | 2242 |
| 2338 if (!m_paused) { | 2243 if (!m_paused) { |
| 2339 m_paused = true; | 2244 m_paused = true; |
| 2340 scheduleTimeupdateEvent(false); | 2245 scheduleTimeupdateEvent(false); |
| 2341 scheduleEvent(EventTypeNames::pause); | 2246 scheduleEvent(EventTypeNames::pause); |
| 2342 | 2247 |
| 2343 // Force an update to official playback position. Automatic updates from | 2248 // Force an update to official playback position. Automatic updates from |
| 2344 // currentPlaybackPosition() will be blocked while m_paused = true. This | 2249 // currentPlaybackPosition() will be blocked while m_paused = true. This |
| 2345 // blocking is desired while paused, but its good to update it one final | 2250 // blocking is desired while paused, but its good to update it one final |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2448 return; | 2353 return; |
| 2449 | 2354 |
| 2450 bool wasAutoplayingMuted = isAutoplayingMuted(); | 2355 bool wasAutoplayingMuted = isAutoplayingMuted(); |
| 2451 bool wasPendingAutoplayMuted = m_autoplayVisibilityObserver && paused() && | 2356 bool wasPendingAutoplayMuted = m_autoplayVisibilityObserver && paused() && |
| 2452 m_muted && isLockedPendingUserGesture(); | 2357 m_muted && isLockedPendingUserGesture(); |
| 2453 | 2358 |
| 2454 if (UserGestureIndicator::processingUserGesture()) | 2359 if (UserGestureIndicator::processingUserGesture()) |
| 2455 unlockUserGesture(); | 2360 unlockUserGesture(); |
| 2456 | 2361 |
| 2457 m_muted = muted; | 2362 m_muted = muted; |
| 2458 m_autoplayHelper->mutedChanged(); | |
| 2459 | 2363 |
| 2460 scheduleEvent(EventTypeNames::volumechange); | 2364 scheduleEvent(EventTypeNames::volumechange); |
| 2461 | 2365 |
| 2462 // If an element autoplayed while muted, it needs to be unlocked to unmute, | 2366 // If an element autoplayed while muted, it needs to be unlocked to unmute, |
| 2463 // otherwise, it will be paused. | 2367 // otherwise, it will be paused. |
| 2464 if (wasAutoplayingMuted) { | 2368 if (wasAutoplayingMuted) { |
| 2465 if (isGestureNeededForPlayback()) { | 2369 if (isGestureNeededForPlayback()) { |
| 2466 pause(); | 2370 pause(); |
| 2467 m_autoplayUmaHelper->recordAutoplayUnmuteStatus( | 2371 m_autoplayUmaHelper->recordAutoplayUnmuteStatus( |
| 2468 AutoplayUnmuteActionStatus::Failure); | 2372 AutoplayUnmuteActionStatus::Failure); |
| (...skipping 869 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3338 if (shouldBePlaying) { | 3242 if (shouldBePlaying) { |
| 3339 setDisplayMode(Video); | 3243 setDisplayMode(Video); |
| 3340 | 3244 |
| 3341 if (!isPlaying) { | 3245 if (!isPlaying) { |
| 3342 // Set rate, muted before calling play in case they were set before the | 3246 // Set rate, muted before calling play in case they were set before the |
| 3343 // media engine was setup. The media engine should just stash the rate | 3247 // media engine was setup. The media engine should just stash the rate |
| 3344 // and muted values since it isn't already playing. | 3248 // and muted values since it isn't already playing. |
| 3345 webMediaPlayer()->setRate(playbackRate()); | 3249 webMediaPlayer()->setRate(playbackRate()); |
| 3346 webMediaPlayer()->setVolume(effectiveMediaVolume()); | 3250 webMediaPlayer()->setVolume(effectiveMediaVolume()); |
| 3347 webMediaPlayer()->play(); | 3251 webMediaPlayer()->play(); |
| 3348 m_autoplayHelper->playbackStarted(); | |
| 3349 } | 3252 } |
| 3350 | 3253 |
| 3351 if (mediaControls()) | 3254 if (mediaControls()) |
| 3352 mediaControls()->playbackStarted(); | 3255 mediaControls()->playbackStarted(); |
| 3353 startPlaybackProgressTimer(); | 3256 startPlaybackProgressTimer(); |
| 3354 m_playing = true; | 3257 m_playing = true; |
| 3355 | 3258 |
| 3356 } else { // Should not be playing right now | 3259 } else { // Should not be playing right now |
| 3357 if (isPlaying) { | 3260 if (isPlaying) { |
| 3358 webMediaPlayer()->pause(); | 3261 webMediaPlayer()->pause(); |
| 3359 m_autoplayHelper->playbackStopped(); | |
| 3360 } | 3262 } |
| 3361 | 3263 |
| 3362 m_playbackProgressTimer.stop(); | 3264 m_playbackProgressTimer.stop(); |
| 3363 m_playing = false; | 3265 m_playing = false; |
| 3364 double time = currentTime(); | 3266 double time = currentTime(); |
| 3365 if (time > m_lastSeekTime) | 3267 if (time > m_lastSeekTime) |
| 3366 addPlayedRange(m_lastSeekTime, time); | 3268 addPlayedRange(m_lastSeekTime, time); |
| 3367 | 3269 |
| 3368 if (mediaControls()) | 3270 if (mediaControls()) |
| 3369 mediaControls()->playbackStopped(); | 3271 mediaControls()->playbackStopped(); |
| (...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3831 visitor->trace(m_mediaSource); | 3733 visitor->trace(m_mediaSource); |
| 3832 visitor->trace(m_audioTracks); | 3734 visitor->trace(m_audioTracks); |
| 3833 visitor->trace(m_videoTracks); | 3735 visitor->trace(m_videoTracks); |
| 3834 visitor->trace(m_cueTimeline); | 3736 visitor->trace(m_cueTimeline); |
| 3835 visitor->trace(m_textTracks); | 3737 visitor->trace(m_textTracks); |
| 3836 visitor->trace(m_textTracksWhenResourceSelectionBegan); | 3738 visitor->trace(m_textTracksWhenResourceSelectionBegan); |
| 3837 visitor->trace(m_playPromiseResolvers); | 3739 visitor->trace(m_playPromiseResolvers); |
| 3838 visitor->trace(m_playPromiseResolveList); | 3740 visitor->trace(m_playPromiseResolveList); |
| 3839 visitor->trace(m_playPromiseRejectList); | 3741 visitor->trace(m_playPromiseRejectList); |
| 3840 visitor->trace(m_audioSourceProvider); | 3742 visitor->trace(m_audioSourceProvider); |
| 3841 visitor->trace(m_autoplayHelperClient); | |
| 3842 visitor->trace(m_autoplayHelper); | |
| 3843 visitor->trace(m_autoplayUmaHelper); | 3743 visitor->trace(m_autoplayUmaHelper); |
| 3844 visitor->trace(m_srcObject); | 3744 visitor->trace(m_srcObject); |
| 3845 visitor->trace(m_autoplayVisibilityObserver); | 3745 visitor->trace(m_autoplayVisibilityObserver); |
| 3846 visitor->template registerWeakMembers<HTMLMediaElement, | 3746 visitor->template registerWeakMembers<HTMLMediaElement, |
| 3847 &HTMLMediaElement::clearWeakMembers>( | 3747 &HTMLMediaElement::clearWeakMembers>( |
| 3848 this); | 3748 this); |
| 3849 Supplementable<HTMLMediaElement>::trace(visitor); | 3749 Supplementable<HTMLMediaElement>::trace(visitor); |
| 3850 HTMLElement::trace(visitor); | 3750 HTMLElement::trace(visitor); |
| 3851 ActiveDOMObject::trace(visitor); | 3751 ActiveDOMObject::trace(visitor); |
| 3852 } | 3752 } |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3910 // - Autoplay is enabled in settings; | 3810 // - Autoplay is enabled in settings; |
| 3911 if (isHTMLVideoElement() && muted() && | 3811 if (isHTMLVideoElement() && muted() && |
| 3912 RuntimeEnabledFeatures::autoplayMutedVideosEnabled() && | 3812 RuntimeEnabledFeatures::autoplayMutedVideosEnabled() && |
| 3913 !(document().settings() && document().settings()->dataSaverEnabled()) && | 3813 !(document().settings() && document().settings()->dataSaverEnabled()) && |
| 3914 !(document().settings() && | 3814 !(document().settings() && |
| 3915 document().settings()->forcePreloadNoneForMediaElements()) && | 3815 document().settings()->forcePreloadNoneForMediaElements()) && |
| 3916 isAutoplayAllowedPerSettings()) { | 3816 isAutoplayAllowedPerSettings()) { |
| 3917 return false; | 3817 return false; |
| 3918 } | 3818 } |
| 3919 | 3819 |
| 3920 if (m_autoplayHelper->isGestureRequirementOverridden()) | |
| 3921 return false; | |
| 3922 | |
| 3923 return true; | 3820 return true; |
| 3924 } | 3821 } |
| 3925 | 3822 |
| 3926 bool HTMLMediaElement::isAutoplayAllowedPerSettings() const { | 3823 bool HTMLMediaElement::isAutoplayAllowedPerSettings() const { |
| 3927 LocalFrame* frame = document().frame(); | 3824 LocalFrame* frame = document().frame(); |
| 3928 if (!frame) | 3825 if (!frame) |
| 3929 return false; | 3826 return false; |
| 3930 FrameLoaderClient* frameLoaderClient = frame->loader().client(); | 3827 FrameLoaderClient* frameLoaderClient = frame->loader().client(); |
| 3931 return frameLoaderClient && frameLoaderClient->allowAutoplay(false); | 3828 return frameLoaderClient && frameLoaderClient->allowAutoplay(false); |
| 3932 } | 3829 } |
| 3933 | 3830 |
| 3934 void HTMLMediaElement::setNetworkState(NetworkState state) { | 3831 void HTMLMediaElement::setNetworkState(NetworkState state) { |
| 3935 if (m_networkState != state) { | 3832 if (m_networkState != state) { |
| 3936 m_networkState = state; | 3833 m_networkState = state; |
| 3937 if (MediaControls* controls = mediaControls()) | 3834 if (MediaControls* controls = mediaControls()) |
| 3938 controls->networkStateChanged(); | 3835 controls->networkStateChanged(); |
| 3939 } | 3836 } |
| 3940 } | 3837 } |
| 3941 | 3838 |
| 3942 void HTMLMediaElement::videoWillBeDrawnToCanvas() const { | 3839 void HTMLMediaElement::videoWillBeDrawnToCanvas() const { |
| 3943 DCHECK(isHTMLVideoElement()); | 3840 DCHECK(isHTMLVideoElement()); |
| 3944 UseCounter::count(document(), UseCounter::VideoInCanvas); | 3841 UseCounter::count(document(), UseCounter::VideoInCanvas); |
| 3945 if (m_autoplayUmaHelper->hasSource() && !m_autoplayUmaHelper->isVisible()) | 3842 if (m_autoplayUmaHelper->hasSource() && !m_autoplayUmaHelper->isVisible()) |
| 3946 UseCounter::count(document(), UseCounter::HiddenAutoplayedVideoInCanvas); | 3843 UseCounter::count(document(), UseCounter::HiddenAutoplayedVideoInCanvas); |
| 3947 } | 3844 } |
| 3948 | 3845 |
| 3949 void HTMLMediaElement::notifyPositionMayHaveChanged( | |
| 3950 const IntRect& visibleRect) { | |
| 3951 m_autoplayHelper->positionChanged(visibleRect); | |
| 3952 } | |
| 3953 | |
| 3954 void HTMLMediaElement::updatePositionNotificationRegistration() { | |
| 3955 m_autoplayHelper->updatePositionNotificationRegistration(); | |
| 3956 } | |
| 3957 | |
| 3958 // TODO(liberato): remove once autoplay gesture override experiment concludes. | |
| 3959 void HTMLMediaElement::triggerAutoplayViewportCheckForTesting() { | |
| 3960 if (FrameView* view = document().view()) | |
| 3961 m_autoplayHelper->positionChanged( | |
| 3962 view->rootFrameToContents(view->computeVisibleArea())); | |
| 3963 m_autoplayHelper->triggerAutoplayViewportCheckForTesting(); | |
| 3964 } | |
| 3965 | |
| 3966 void HTMLMediaElement::scheduleResolvePlayPromises() { | 3846 void HTMLMediaElement::scheduleResolvePlayPromises() { |
| 3967 // TODO(mlamouri): per spec, we should create a new task but we can't create | 3847 // TODO(mlamouri): per spec, we should create a new task but we can't create |
| 3968 // a new cancellable task without cancelling the previous one. There are two | 3848 // a new cancellable task without cancelling the previous one. There are two |
| 3969 // approaches then: cancel the previous task and create a new one with the | 3849 // approaches then: cancel the previous task and create a new one with the |
| 3970 // appended promise list or append the new promise to the current list. The | 3850 // appended promise list or append the new promise to the current list. The |
| 3971 // latter approach is preferred because it might be the less observable | 3851 // latter approach is preferred because it might be the less observable |
| 3972 // change. | 3852 // change. |
| 3973 DCHECK(m_playPromiseResolveList.isEmpty() || | 3853 DCHECK(m_playPromiseResolveList.isEmpty() || |
| 3974 m_playPromiseResolveTaskHandle.isActive()); | 3854 m_playPromiseResolveTaskHandle.isActive()); |
| 3975 if (m_playPromiseResolvers.isEmpty()) | 3855 if (m_playPromiseResolvers.isEmpty()) |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4154 } | 4034 } |
| 4155 | 4035 |
| 4156 DEFINE_TRACE(HTMLMediaElement::AudioClientImpl) { | 4036 DEFINE_TRACE(HTMLMediaElement::AudioClientImpl) { |
| 4157 visitor->trace(m_client); | 4037 visitor->trace(m_client); |
| 4158 } | 4038 } |
| 4159 | 4039 |
| 4160 DEFINE_TRACE(HTMLMediaElement::AudioSourceProviderImpl) { | 4040 DEFINE_TRACE(HTMLMediaElement::AudioSourceProviderImpl) { |
| 4161 visitor->trace(m_client); | 4041 visitor->trace(m_client); |
| 4162 } | 4042 } |
| 4163 | 4043 |
| 4164 HTMLMediaElement::AutoplayHelperClientImpl::~AutoplayHelperClientImpl() {} | |
| 4165 | |
| 4166 bool HTMLMediaElement::AutoplayHelperClientImpl::isLegacyViewportType() { | |
| 4167 return m_element->document().viewportDescription().isLegacyViewportType(); | |
| 4168 } | |
| 4169 | |
| 4170 PageVisibilityState | |
| 4171 HTMLMediaElement::AutoplayHelperClientImpl::pageVisibilityState() const { | |
| 4172 return m_element->document().pageVisibilityState(); | |
| 4173 } | |
| 4174 | |
| 4175 String HTMLMediaElement::AutoplayHelperClientImpl::autoplayExperimentMode() | |
| 4176 const { | |
| 4177 String mode; | |
| 4178 if (m_element->document().settings()) | |
| 4179 mode = m_element->document().settings()->autoplayExperimentMode(); | |
| 4180 | |
| 4181 return mode; | |
| 4182 } | |
| 4183 | |
| 4184 bool HTMLMediaElement::AutoplayHelperClientImpl::isAutoplayAllowedPerSettings() | |
| 4185 const { | |
| 4186 return m_element->isAutoplayAllowedPerSettings(); | |
| 4187 } | |
| 4188 | |
| 4189 void HTMLMediaElement::AutoplayHelperClientImpl::setRequestPositionUpdates( | |
| 4190 bool request) { | |
| 4191 if (LayoutObject* layoutObject = m_element->layoutObject()) { | |
| 4192 LayoutMediaItem layoutMediaItem = | |
| 4193 LayoutMediaItem(toLayoutMedia(layoutObject)); | |
| 4194 layoutMediaItem.setRequestPositionUpdates(request); | |
| 4195 } | |
| 4196 } | |
| 4197 | |
| 4198 IntRect HTMLMediaElement::AutoplayHelperClientImpl::absoluteBoundingBoxRect() | |
| 4199 const { | |
| 4200 IntRect result; | |
| 4201 if (LayoutObject* object = m_element->layoutObject()) | |
| 4202 result = object->absoluteBoundingBoxRect(); | |
| 4203 return result; | |
| 4204 } | |
| 4205 | |
| 4206 } // namespace blink | 4044 } // namespace blink |
| OLD | NEW |