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

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

Issue 2813303005: [Blink>Media] Moving autoplay logic to AutoplayPolicy (Closed)
Patch Set: fixed event order for setMuted and added comments Created 3 years, 8 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 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 20 matching lines...) Expand all
31 #include "bindings/core/v8/Microtask.h" 31 #include "bindings/core/v8/Microtask.h"
32 #include "bindings/core/v8/ScriptController.h" 32 #include "bindings/core/v8/ScriptController.h"
33 #include "bindings/core/v8/ScriptEventListener.h" 33 #include "bindings/core/v8/ScriptEventListener.h"
34 #include "bindings/core/v8/ScriptPromiseResolver.h" 34 #include "bindings/core/v8/ScriptPromiseResolver.h"
35 #include "core/HTMLNames.h" 35 #include "core/HTMLNames.h"
36 #include "core/css/MediaList.h" 36 #include "core/css/MediaList.h"
37 #include "core/dom/Attribute.h" 37 #include "core/dom/Attribute.h"
38 #include "core/dom/DOMException.h" 38 #include "core/dom/DOMException.h"
39 #include "core/dom/DocumentUserGestureToken.h" 39 #include "core/dom/DocumentUserGestureToken.h"
40 #include "core/dom/ElementTraversal.h" 40 #include "core/dom/ElementTraversal.h"
41 #include "core/dom/ElementVisibilityObserver.h"
42 #include "core/dom/Fullscreen.h" 41 #include "core/dom/Fullscreen.h"
43 #include "core/dom/TaskRunnerHelper.h" 42 #include "core/dom/TaskRunnerHelper.h"
44 #include "core/dom/shadow/ShadowRoot.h" 43 #include "core/dom/shadow/ShadowRoot.h"
45 #include "core/events/Event.h" 44 #include "core/events/Event.h"
46 #include "core/frame/ContentSettingsClient.h"
47 #include "core/frame/FrameView.h" 45 #include "core/frame/FrameView.h"
48 #include "core/frame/LocalFrame.h" 46 #include "core/frame/LocalFrame.h"
49 #include "core/frame/LocalFrameClient.h" 47 #include "core/frame/LocalFrameClient.h"
50 #include "core/frame/Settings.h" 48 #include "core/frame/Settings.h"
51 #include "core/frame/UseCounter.h" 49 #include "core/frame/UseCounter.h"
52 #include "core/frame/csp/ContentSecurityPolicy.h" 50 #include "core/frame/csp/ContentSecurityPolicy.h"
53 #include "core/html/HTMLSourceElement.h" 51 #include "core/html/HTMLSourceElement.h"
54 #include "core/html/HTMLTrackElement.h" 52 #include "core/html/HTMLTrackElement.h"
55 #include "core/html/TimeRanges.h" 53 #include "core/html/TimeRanges.h"
54 #include "core/html/media/AutoplayPolicy.h"
56 #include "core/html/media/AutoplayUmaHelper.h" 55 #include "core/html/media/AutoplayUmaHelper.h"
57 #include "core/html/media/HTMLMediaElementControlsList.h" 56 #include "core/html/media/HTMLMediaElementControlsList.h"
58 #include "core/html/media/HTMLMediaSource.h" 57 #include "core/html/media/HTMLMediaSource.h"
59 #include "core/html/media/MediaControls.h" 58 #include "core/html/media/MediaControls.h"
60 #include "core/html/media/MediaError.h" 59 #include "core/html/media/MediaError.h"
61 #include "core/html/media/MediaFragmentURIParser.h" 60 #include "core/html/media/MediaFragmentURIParser.h"
62 #include "core/html/track/AudioTrack.h" 61 #include "core/html/track/AudioTrack.h"
63 #include "core/html/track/AudioTrackList.h" 62 #include "core/html/track/AudioTrackList.h"
64 #include "core/html/track/AutomaticTrackSelection.h" 63 #include "core/html/track/AutomaticTrackSelection.h"
65 #include "core/html/track/CueTimeline.h" 64 #include "core/html/track/CueTimeline.h"
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 case WebMediaPlayer::kPreloadMetaData: 325 case WebMediaPlayer::kPreloadMetaData:
327 return "metadata"; 326 return "metadata";
328 case WebMediaPlayer::kPreloadAuto: 327 case WebMediaPlayer::kPreloadAuto:
329 return "auto"; 328 return "auto";
330 } 329 }
331 330
332 NOTREACHED(); 331 NOTREACHED();
333 return String(); 332 return String();
334 } 333 }
335 334
336 bool IsDocumentCrossOrigin(Document& document) {
337 const LocalFrame* frame = document.GetFrame();
338 return frame && frame->IsCrossOriginSubframe();
339 }
340
341 bool IsDocumentWhitelisted(Document& document) {
342 DCHECK(document.GetSettings());
343
344 const String& whitelist_scope =
345 document.GetSettings()->GetMediaPlaybackGestureWhitelistScope();
346 if (whitelist_scope.IsNull() || whitelist_scope.IsEmpty())
347 return false;
348
349 return document.Url().GetString().StartsWith(whitelist_scope);
350 }
351
352 // Return true if and only if the document settings specifies media playback
353 // requires user gesture.
354 bool ComputeLockedPendingUserGesture(Document& document) {
355 if (!document.GetSettings())
356 return false;
357
358 if (IsDocumentWhitelisted(document)) {
359 return false;
360 }
361
362 if (document.GetSettings()
363 ->GetCrossOriginMediaPlaybackRequiresUserGesture() &&
364 IsDocumentCrossOrigin(document)) {
365 return true;
366 }
367
368 return document.GetSettings()->GetMediaPlaybackRequiresUserGesture();
369 }
370
371 std::unique_ptr<MediaControls::Factory>& MediaControlsFactory() { 335 std::unique_ptr<MediaControls::Factory>& MediaControlsFactory() {
372 DEFINE_STATIC_LOCAL(std::unique_ptr<MediaControls::Factory>, 336 DEFINE_STATIC_LOCAL(std::unique_ptr<MediaControls::Factory>,
373 media_controls_factory, ()); 337 media_controls_factory, ());
374 return media_controls_factory; 338 return media_controls_factory;
375 } 339 }
376 340
377 } // anonymous namespace 341 } // anonymous namespace
378 342
379 MIMETypeRegistry::SupportsType HTMLMediaElement::GetSupportsType( 343 MIMETypeRegistry::SupportsType HTMLMediaElement::GetSupportsType(
380 const ContentType& content_type) { 344 const ContentType& content_type) {
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 deferred_load_timer_( 462 deferred_load_timer_(
499 TaskRunnerHelper::Get(TaskType::kUnthrottled, &document), 463 TaskRunnerHelper::Get(TaskType::kUnthrottled, &document),
500 this, 464 this,
501 &HTMLMediaElement::DeferredLoadTimerFired), 465 &HTMLMediaElement::DeferredLoadTimerFired),
502 web_layer_(nullptr), 466 web_layer_(nullptr),
503 display_mode_(kUnknown), 467 display_mode_(kUnknown),
504 official_playback_position_(0), 468 official_playback_position_(0),
505 official_playback_position_needs_update_(true), 469 official_playback_position_needs_update_(true),
506 fragment_end_time_(std::numeric_limits<double>::quiet_NaN()), 470 fragment_end_time_(std::numeric_limits<double>::quiet_NaN()),
507 pending_action_flags_(0), 471 pending_action_flags_(0),
508 locked_pending_user_gesture_(false),
509 locked_pending_user_gesture_if_cross_origin_experiment_enabled_(true),
510 playing_(false), 472 playing_(false),
511 should_delay_load_event_(false), 473 should_delay_load_event_(false),
512 have_fired_loaded_data_(false), 474 have_fired_loaded_data_(false),
513 can_autoplay_(true), 475 can_autoplay_(true),
514 muted_(false), 476 muted_(false),
515 paused_(true), 477 paused_(true),
516 seeking_(false), 478 seeking_(false),
517 sent_stalled_event_(false), 479 sent_stalled_event_(false),
518 ignore_preload_none_(false), 480 ignore_preload_none_(false),
519 text_tracks_visible_(false), 481 text_tracks_visible_(false),
520 should_perform_automatic_track_selection_(true), 482 should_perform_automatic_track_selection_(true),
521 tracks_are_ready_(true), 483 tracks_are_ready_(true),
522 processing_preference_change_(false), 484 processing_preference_change_(false),
523 playing_remotely_(false), 485 playing_remotely_(false),
524 in_overlay_fullscreen_video_(false), 486 in_overlay_fullscreen_video_(false),
525 mostly_filling_viewport_(false), 487 mostly_filling_viewport_(false),
526 audio_tracks_(this, AudioTrackList::Create(*this)), 488 audio_tracks_(this, AudioTrackList::Create(*this)),
527 video_tracks_(this, VideoTrackList::Create(*this)), 489 video_tracks_(this, VideoTrackList::Create(*this)),
528 text_tracks_(this, nullptr), 490 text_tracks_(this, nullptr),
529 audio_source_node_(nullptr), 491 audio_source_node_(nullptr),
492 autoplay_policy_(new AutoplayPolicy(this)),
530 autoplay_uma_helper_(AutoplayUmaHelper::Create(this)), 493 autoplay_uma_helper_(AutoplayUmaHelper::Create(this)),
531 remote_playback_client_(nullptr), 494 remote_playback_client_(nullptr),
532 autoplay_visibility_observer_(nullptr),
533 media_controls_(nullptr), 495 media_controls_(nullptr),
534 controls_list_(HTMLMediaElementControlsList::Create(this)) { 496 controls_list_(HTMLMediaElementControlsList::Create(this)) {
535 BLINK_MEDIA_LOG << "HTMLMediaElement(" << (void*)this << ")"; 497 BLINK_MEDIA_LOG << "HTMLMediaElement(" << (void*)this << ")";
536 498
537 locked_pending_user_gesture_ = ComputeLockedPendingUserGesture(document);
538 locked_pending_user_gesture_if_cross_origin_experiment_enabled_ =
539 IsDocumentCrossOrigin(document);
540
541 LocalFrame* frame = document.GetFrame(); 499 LocalFrame* frame = document.GetFrame();
542 if (frame) { 500 if (frame) {
543 remote_playback_client_ = 501 remote_playback_client_ =
544 frame->Loader().Client()->CreateWebRemotePlaybackClient(*this); 502 frame->Loader().Client()->CreateWebRemotePlaybackClient(*this);
545 } 503 }
546 504
547 SetHasCustomStyleCallbacks(); 505 SetHasCustomStyleCallbacks();
548 AddElementToDocumentMap(this, &document); 506 AddElementToDocumentMap(this, &document);
549 507
550 UseCounter::Count(document, UseCounter::kHTMLMediaElement); 508 UseCounter::Count(document, UseCounter::kHTMLMediaElement);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
585 audio_tracks_timer_.MoveToNewTaskRunner( 543 audio_tracks_timer_.MoveToNewTaskRunner(
586 TaskRunnerHelper::Get(TaskType::kUnthrottled, &GetDocument())); 544 TaskRunnerHelper::Get(TaskType::kUnthrottled, &GetDocument()));
587 viewport_fill_debouncer_timer_.MoveToNewTaskRunner( 545 viewport_fill_debouncer_timer_.MoveToNewTaskRunner(
588 TaskRunnerHelper::Get(TaskType::kUnthrottled, &GetDocument())); 546 TaskRunnerHelper::Get(TaskType::kUnthrottled, &GetDocument()));
589 check_viewport_intersection_timer_.MoveToNewTaskRunner( 547 check_viewport_intersection_timer_.MoveToNewTaskRunner(
590 TaskRunnerHelper::Get(TaskType::kUnthrottled, &GetDocument())); 548 TaskRunnerHelper::Get(TaskType::kUnthrottled, &GetDocument()));
591 deferred_load_timer_.MoveToNewTaskRunner( 549 deferred_load_timer_.MoveToNewTaskRunner(
592 TaskRunnerHelper::Get(TaskType::kUnthrottled, &GetDocument())); 550 TaskRunnerHelper::Get(TaskType::kUnthrottled, &GetDocument()));
593 551
594 autoplay_uma_helper_->DidMoveToNewDocument(old_document); 552 autoplay_uma_helper_->DidMoveToNewDocument(old_document);
595 // If any experiment is enabled, then we want to enable a user gesture by 553 autoplay_policy_->DidMoveToNewDocument(old_document);
596 // default, otherwise the experiment does nothing.
597 bool old_document_requires_user_gesture =
598 ComputeLockedPendingUserGesture(old_document);
599 bool new_document_requires_user_gesture =
600 ComputeLockedPendingUserGesture(GetDocument());
601 if (new_document_requires_user_gesture && !old_document_requires_user_gesture)
602 locked_pending_user_gesture_ = true;
603 554
604 if (should_delay_load_event_) { 555 if (should_delay_load_event_) {
605 GetDocument().IncrementLoadEventDelayCount(); 556 GetDocument().IncrementLoadEventDelayCount();
606 // Note: Keeping the load event delay count increment on oldDocument that 557 // Note: Keeping the load event delay count increment on oldDocument that
607 // was added when m_shouldDelayLoadEvent was set so that destruction of 558 // was added when m_shouldDelayLoadEvent was set so that destruction of
608 // m_webMediaPlayer can not cause load event dispatching in oldDocument. 559 // m_webMediaPlayer can not cause load event dispatching in oldDocument.
609 } else { 560 } else {
610 // Incrementing the load event delay count so that destruction of 561 // Incrementing the load event delay count so that destruction of
611 // m_webMediaPlayer can not cause load event dispatching in oldDocument. 562 // m_webMediaPlayer can not cause load event dispatching in oldDocument.
612 old_document.IncrementLoadEventDelayCount(); 563 old_document.IncrementLoadEventDelayCount();
613 } 564 }
614 565
615 if (IsDocumentCrossOrigin(GetDocument()) &&
616 !IsDocumentCrossOrigin(old_document))
617 locked_pending_user_gesture_if_cross_origin_experiment_enabled_ = true;
618
619 RemoveElementFromDocumentMap(this, &old_document); 566 RemoveElementFromDocumentMap(this, &old_document);
620 AddElementToDocumentMap(this, &GetDocument()); 567 AddElementToDocumentMap(this, &GetDocument());
621 568
622 // FIXME: This is a temporary fix to prevent this object from causing the 569 // FIXME: This is a temporary fix to prevent this object from causing the
623 // MediaPlayer to dereference LocalFrame and FrameLoader pointers from the 570 // MediaPlayer to dereference LocalFrame and FrameLoader pointers from the
624 // previous document. This restarts the load, as if the src attribute had been 571 // previous document. This restarts the load, as if the src attribute had been
625 // set. A proper fix would provide a mechanism to allow this object to 572 // set. A proper fix would provide a mechanism to allow this object to
626 // refresh the MediaPlayer's LocalFrame and FrameLoader references on document 573 // refresh the MediaPlayer's LocalFrame and FrameLoader references on document
627 // changes so that playback can be resumed properly. 574 // changes so that playback can be resumed properly.
628 ignore_preload_none_ = false; 575 ignore_preload_none_ = false;
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
838 785
839 BLINK_MEDIA_LOG << "canPlayType(" << (void*)this << ", " << mime_type 786 BLINK_MEDIA_LOG << "canPlayType(" << (void*)this << ", " << mime_type
840 << ") -> " << can_play; 787 << ") -> " << can_play;
841 788
842 return can_play; 789 return can_play;
843 } 790 }
844 791
845 void HTMLMediaElement::load() { 792 void HTMLMediaElement::load() {
846 BLINK_MEDIA_LOG << "load(" << (void*)this << ")"; 793 BLINK_MEDIA_LOG << "load(" << (void*)this << ")";
847 794
848 if (IsLockedPendingUserGesture() && 795 autoplay_policy_->TryUnlockingUserGesture();
849 UserGestureIndicator::UtilizeUserGesture()) {
850 UnlockUserGesture();
851 }
852 796
853 ignore_preload_none_ = true; 797 ignore_preload_none_ = true;
854 InvokeLoadAlgorithm(); 798 InvokeLoadAlgorithm();
855 } 799 }
856 800
857 // TODO(srirama.m): Currently m_ignorePreloadNone is reset before calling 801 // TODO(srirama.m): Currently m_ignorePreloadNone is reset before calling
858 // invokeLoadAlgorithm() in all places except load(). Move it inside here 802 // invokeLoadAlgorithm() in all places except load(). Move it inside here
859 // once microtask is implemented for "Await a stable state" step 803 // once microtask is implemented for "Await a stable state" step
860 // in resource selection algorithm. 804 // in resource selection algorithm.
861 void HTMLMediaElement::InvokeLoadAlgorithm() { 805 void HTMLMediaElement::InvokeLoadAlgorithm() {
(...skipping 612 matching lines...) Expand 10 before | Expand all | Expand 10 after
1474 // (vs. non-CORS-enabled or failed). 1418 // (vs. non-CORS-enabled or failed).
1475 // taintsCanvas() does checkAccess() on the URL plus allow data sources, 1419 // taintsCanvas() does checkAccess() on the URL plus allow data sources,
1476 // to ensure that it is not a URL that requires CORS (basically same 1420 // to ensure that it is not a URL that requires CORS (basically same
1477 // origin). 1421 // origin).
1478 return HasSingleSecurityOrigin() && 1422 return HasSingleSecurityOrigin() &&
1479 ((GetWebMediaPlayer() && 1423 ((GetWebMediaPlayer() &&
1480 GetWebMediaPlayer()->DidPassCORSAccessCheck()) || 1424 GetWebMediaPlayer()->DidPassCORSAccessCheck()) ||
1481 !origin->TaintsCanvas(currentSrc())); 1425 !origin->TaintsCanvas(currentSrc()));
1482 } 1426 }
1483 1427
1484 bool HTMLMediaElement::IsInCrossOriginFrame() const {
1485 return IsDocumentCrossOrigin(GetDocument());
1486 }
1487
1488 void HTMLMediaElement::StartProgressEventTimer() { 1428 void HTMLMediaElement::StartProgressEventTimer() {
1489 if (progress_event_timer_.IsActive()) 1429 if (progress_event_timer_.IsActive())
1490 return; 1430 return;
1491 1431
1492 previous_progress_time_ = WTF::CurrentTime(); 1432 previous_progress_time_ = WTF::CurrentTime();
1493 // 350ms is not magic, it is in the spec! 1433 // 350ms is not magic, it is in the spec!
1494 progress_event_timer_.StartRepeating(0.350, BLINK_FROM_HERE); 1434 progress_event_timer_.StartRepeating(0.350, BLINK_FROM_HERE);
1495 } 1435 }
1496 1436
1497 void HTMLMediaElement::WaitForSourceChange() { 1437 void HTMLMediaElement::WaitForSourceChange() {
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after
1836 if (old_state <= kHaveCurrentData) { 1776 if (old_state <= kHaveCurrentData) {
1837 ScheduleEvent(EventTypeNames::canplay); 1777 ScheduleEvent(EventTypeNames::canplay);
1838 if (is_potentially_playing) 1778 if (is_potentially_playing)
1839 ScheduleNotifyPlaying(); 1779 ScheduleNotifyPlaying();
1840 } 1780 }
1841 1781
1842 // Check for autoplay, and record metrics about it if needed. 1782 // Check for autoplay, and record metrics about it if needed.
1843 if (ShouldAutoplay()) { 1783 if (ShouldAutoplay()) {
1844 autoplay_uma_helper_->OnAutoplayInitiated(AutoplaySource::kAttribute); 1784 autoplay_uma_helper_->OnAutoplayInitiated(AutoplaySource::kAttribute);
1845 1785
1846 if (!IsGestureNeededForPlayback()) { 1786 if (!autoplay_policy_->IsGestureNeededForPlayback()) {
1847 if (IsGestureNeededForPlaybackIfCrossOriginExperimentEnabled()) { 1787 if (autoplay_policy_
1788 ->IsGestureNeededForPlaybackIfCrossOriginExperimentEnabled()) {
1848 autoplay_uma_helper_->RecordCrossOriginAutoplayResult( 1789 autoplay_uma_helper_->RecordCrossOriginAutoplayResult(
1849 CrossOriginAutoplayResult::kAutoplayBlocked); 1790 CrossOriginAutoplayResult::kAutoplayBlocked);
1850 } else { 1791 } else {
1851 autoplay_uma_helper_->RecordCrossOriginAutoplayResult( 1792 autoplay_uma_helper_->RecordCrossOriginAutoplayResult(
1852 CrossOriginAutoplayResult::kAutoplayAllowed); 1793 CrossOriginAutoplayResult::kAutoplayAllowed);
1853 } 1794 }
1854 if (IsHTMLVideoElement() && muted() && 1795 if (autoplay_policy_->IsEligibleForAutoplayMuted()) {
1855 RuntimeEnabledFeatures::autoplayMutedVideosEnabled()) { 1796 autoplay_policy_->StartAutoplayMutedWhenVisible();
1856 // We might end up in a situation where the previous
1857 // observer didn't had time to fire yet. We can avoid
1858 // creating a new one in this case.
1859 if (!autoplay_visibility_observer_) {
1860 autoplay_visibility_observer_ = new ElementVisibilityObserver(
1861 this,
1862 WTF::Bind(&HTMLMediaElement::OnVisibilityChangedForAutoplay,
1863 WrapWeakPersistent(this)));
1864 autoplay_visibility_observer_->Start();
1865 }
1866 } else { 1797 } else {
1867 paused_ = false; 1798 paused_ = false;
1868 ScheduleEvent(EventTypeNames::play); 1799 ScheduleEvent(EventTypeNames::play);
1869 ScheduleNotifyPlaying(); 1800 ScheduleNotifyPlaying();
1870 can_autoplay_ = false; 1801 can_autoplay_ = false;
1871 } 1802 }
1872 } else { 1803 } else {
1873 autoplay_uma_helper_->RecordCrossOriginAutoplayResult( 1804 autoplay_uma_helper_->RecordCrossOriginAutoplayResult(
1874 CrossOriginAutoplayResult::kAutoplayBlocked); 1805 CrossOriginAutoplayResult::kAutoplayBlocked);
1875 } 1806 }
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after
2276 // https://crbug.com/310450 2207 // https://crbug.com/310450
2277 UseCounter::Count(GetDocument(), UseCounter::kHTMLMediaElementPreloadDefault); 2208 UseCounter::Count(GetDocument(), UseCounter::kHTMLMediaElementPreloadDefault);
2278 return WebMediaPlayer::kPreloadAuto; 2209 return WebMediaPlayer::kPreloadAuto;
2279 } 2210 }
2280 2211
2281 String HTMLMediaElement::EffectivePreload() const { 2212 String HTMLMediaElement::EffectivePreload() const {
2282 return PreloadTypeToString(EffectivePreloadType()); 2213 return PreloadTypeToString(EffectivePreloadType());
2283 } 2214 }
2284 2215
2285 WebMediaPlayer::Preload HTMLMediaElement::EffectivePreloadType() const { 2216 WebMediaPlayer::Preload HTMLMediaElement::EffectivePreloadType() const {
2286 if (Autoplay() && !IsGestureNeededForPlayback()) 2217 if (Autoplay() && !autoplay_policy_->IsGestureNeededForPlayback())
2287 return WebMediaPlayer::kPreloadAuto; 2218 return WebMediaPlayer::kPreloadAuto;
2288 2219
2289 WebMediaPlayer::Preload preload = PreloadType(); 2220 WebMediaPlayer::Preload preload = PreloadType();
2290 if (ignore_preload_none_ && preload == WebMediaPlayer::kPreloadNone) 2221 if (ignore_preload_none_ && preload == WebMediaPlayer::kPreloadNone)
2291 return WebMediaPlayer::kPreloadMetaData; 2222 return WebMediaPlayer::kPreloadMetaData;
2292 2223
2293 return preload; 2224 return preload;
2294 } 2225 }
2295 2226
2296 ScriptPromise HTMLMediaElement::playForBindings(ScriptState* script_state) { 2227 ScriptPromise HTMLMediaElement::playForBindings(ScriptState* script_state) {
(...skipping 25 matching lines...) Expand all
2322 resolver->Reject(DOMException::Create(code.Get(), message)); 2253 resolver->Reject(DOMException::Create(code.Get(), message));
2323 return promise; 2254 return promise;
2324 } 2255 }
2325 2256
2326 return promise; 2257 return promise;
2327 } 2258 }
2328 2259
2329 Nullable<ExceptionCode> HTMLMediaElement::Play() { 2260 Nullable<ExceptionCode> HTMLMediaElement::Play() {
2330 BLINK_MEDIA_LOG << "play(" << (void*)this << ")"; 2261 BLINK_MEDIA_LOG << "play(" << (void*)this << ")";
2331 2262
2332 if (!UserGestureIndicator::ProcessingUserGesture()) { 2263 // If we're already playing, then this play would do nothing anyway.
2333 autoplay_uma_helper_->OnAutoplayInitiated(AutoplaySource::kMethod); 2264 // Call playInternal to handle scheduling the promise resolution.
2334 if (IsGestureNeededForPlayback()) { 2265 if (!paused_) {
2335 // If we're already playing, then this play would do nothing anyway. 2266 PlayInternal();
2336 // Call playInternal to handle scheduling the promise resolution. 2267 return nullptr;
2337 if (!paused_) { 2268 }
mlamouri (slow - plz ping) 2017/04/18 13:28:28 The logic is slightly changing with this change. I
Zhiqiang Zhang (Slow) 2017/04/18 16:56:44 OK, I moved the code a bit so it should have the s
2338 PlayInternal();
2339 return nullptr;
2340 }
2341 2269
2342 autoplay_uma_helper_->RecordCrossOriginAutoplayResult( 2270 autoplay_policy_->StopAutoplayMutedWhenVisible();
2343 CrossOriginAutoplayResult::kAutoplayBlocked);
2344 String message = ExceptionMessages::FailedToExecute(
2345 "play", "HTMLMediaElement",
2346 "API can only be initiated by a user gesture.");
2347 GetDocument().AddConsoleMessage(ConsoleMessage::Create(
2348 kJSMessageSource, kWarningMessageLevel, message));
2349 return kNotAllowedError;
2350 } else {
2351 if (IsGestureNeededForPlaybackIfCrossOriginExperimentEnabled()) {
2352 autoplay_uma_helper_->RecordCrossOriginAutoplayResult(
2353 CrossOriginAutoplayResult::kAutoplayBlocked);
2354 } else {
2355 autoplay_uma_helper_->RecordCrossOriginAutoplayResult(
2356 CrossOriginAutoplayResult::kAutoplayAllowed);
2357 }
2358 }
2359 } else {
2360 autoplay_uma_helper_->RecordCrossOriginAutoplayResult(
2361 CrossOriginAutoplayResult::kPlayedWithGesture);
2362 UserGestureIndicator::UtilizeUserGesture();
2363 UnlockUserGesture();
2364 }
2365 2271
2366 if (error_ && error_->code() == MediaError::kMediaErrSrcNotSupported) 2272 if (error_ && error_->code() == MediaError::kMediaErrSrcNotSupported)
2367 return kNotSupportedError; 2273 return kNotSupportedError;
2368 2274
2369 if (autoplay_visibility_observer_) { 2275 // The only place to call IsAutoplayAllowedFromPlayMethod(), don't call from
2370 autoplay_visibility_observer_->Stop(); 2276 // anywhere else!
mlamouri (slow - plz ping) 2017/04/18 13:28:28 Comment is out of date, right?
Zhiqiang Zhang (Slow) 2017/04/18 16:56:44 Done.
2371 autoplay_visibility_observer_ = nullptr; 2277 Nullable<ExceptionCode> exception_code =
2278 autoplay_policy_->CheckPlayMethodAllowed();
2279
2280 if (exception_code == kNotAllowedError) {
2281 String message = ExceptionMessages::FailedToExecute(
2282 "play", "HTMLMediaElement",
2283 "API can only be initiated by a user gesture.");
2284 GetDocument().AddConsoleMessage(ConsoleMessage::Create(
2285 kJSMessageSource, kWarningMessageLevel, message));
2286 return exception_code;
2372 } 2287 }
2373 2288
2289 DCHECK(exception_code.IsNull());
2290
2374 PlayInternal(); 2291 PlayInternal();
2375 2292
2376 return nullptr; 2293 return nullptr;
2377 } 2294 }
2378 2295
2379 void HTMLMediaElement::PlayInternal() { 2296 void HTMLMediaElement::PlayInternal() {
2380 BLINK_MEDIA_LOG << "playInternal(" << (void*)this << ")"; 2297 BLINK_MEDIA_LOG << "playInternal(" << (void*)this << ")";
2381 2298
2382 // 4.8.12.8. Playing the media resource 2299 // 4.8.12.8. Playing the media resource
2383 if (network_state_ == kNetworkEmpty) 2300 if (network_state_ == kNetworkEmpty)
(...skipping 19 matching lines...) Expand all
2403 2320
2404 can_autoplay_ = false; 2321 can_autoplay_ = false;
2405 2322
2406 SetIgnorePreloadNone(); 2323 SetIgnorePreloadNone();
2407 UpdatePlayState(); 2324 UpdatePlayState();
2408 } 2325 }
2409 2326
2410 void HTMLMediaElement::pause() { 2327 void HTMLMediaElement::pause() {
2411 BLINK_MEDIA_LOG << "pause(" << (void*)this << ")"; 2328 BLINK_MEDIA_LOG << "pause(" << (void*)this << ")";
2412 2329
2413 if (autoplay_visibility_observer_) { 2330 autoplay_policy_->StopAutoplayMutedWhenVisible();
2414 autoplay_visibility_observer_->Stop();
2415 autoplay_visibility_observer_ = nullptr;
2416 }
2417
2418 PauseInternal(); 2331 PauseInternal();
2419 } 2332 }
2420 2333
2421 void HTMLMediaElement::PauseInternal() { 2334 void HTMLMediaElement::PauseInternal() {
2422 BLINK_MEDIA_LOG << "pauseInternal(" << (void*)this << ")"; 2335 BLINK_MEDIA_LOG << "pauseInternal(" << (void*)this << ")";
2423 2336
2424 if (network_state_ == kNetworkEmpty) 2337 if (network_state_ == kNetworkEmpty)
2425 InvokeResourceSelectionAlgorithm(); 2338 InvokeResourceSelectionAlgorithm();
2426 2339
2427 can_autoplay_ = false; 2340 can_autoplay_ = false;
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
2555 return muted_; 2468 return muted_;
2556 } 2469 }
2557 2470
2558 void HTMLMediaElement::setMuted(bool muted) { 2471 void HTMLMediaElement::setMuted(bool muted) {
2559 BLINK_MEDIA_LOG << "setMuted(" << (void*)this << ", " << BoolString(muted) 2472 BLINK_MEDIA_LOG << "setMuted(" << (void*)this << ", " << BoolString(muted)
2560 << ")"; 2473 << ")";
2561 2474
2562 if (muted_ == muted) 2475 if (muted_ == muted)
2563 return; 2476 return;
2564 2477
2565 bool was_autoplaying_muted = IsAutoplayingMuted(); 2478 // TODO(zqzhang): use TryUnlockingUserGesture?
2566 bool was_pending_autoplay_muted = autoplay_visibility_observer_ && paused() && 2479 if (UserGestureIndicator::ProcessingUserGesture())
2567 muted_ && IsLockedPendingUserGesture(); 2480 autoplay_policy_->UnlockUserGesture();
2568 2481
2569 if (UserGestureIndicator::ProcessingUserGesture()) 2482 bool should_pause_after_unmute =
2570 UnlockUserGesture(); 2483 autoplay_policy_->CheckUnmuteShouldPauseAutoplay();
mlamouri (slow - plz ping) 2017/04/18 13:28:28 Not sure this is at the right place. Should this b
Zhiqiang Zhang (Slow) 2017/04/18 16:56:44 The logic won't change actually. The original logi
2571 2484
2572 muted_ = muted; 2485 muted_ = muted;
2573 2486
2574 ScheduleEvent(EventTypeNames::volumechange); 2487 ScheduleEvent(EventTypeNames::volumechange);
2575 2488
2576 // If an element autoplayed while muted, it needs to be unlocked to unmute, 2489 if (should_pause_after_unmute)
2577 // otherwise, it will be paused. 2490 pause();
2578 if (was_autoplaying_muted) {
2579 if (IsGestureNeededForPlayback()) {
2580 pause();
2581 autoplay_uma_helper_->RecordAutoplayUnmuteStatus(
2582 AutoplayUnmuteActionStatus::kFailure);
2583 } else {
2584 autoplay_uma_helper_->RecordAutoplayUnmuteStatus(
2585 AutoplayUnmuteActionStatus::kSuccess);
2586 }
2587 }
2588 2491
2589 // This is called after the volumechange event to make sure isAutoplayingMuted 2492 // This is called after the volumechange event to make sure isAutoplayingMuted
2590 // returns the right value when webMediaPlayer receives the volume update. 2493 // returns the right value when webMediaPlayer receives the volume update.
2591 if (GetWebMediaPlayer()) 2494 if (GetWebMediaPlayer())
2592 GetWebMediaPlayer()->SetVolume(EffectiveMediaVolume()); 2495 GetWebMediaPlayer()->SetVolume(EffectiveMediaVolume());
2593 2496
2594 // If an element was a candidate for autoplay muted but not visible, it will 2497 autoplay_policy_->StopAutoplayMutedWhenVisible();
2595 // have a visibility observer ready to start its playback.
2596 if (was_pending_autoplay_muted) {
2597 autoplay_visibility_observer_->Stop();
2598 autoplay_visibility_observer_ = nullptr;
2599 }
2600 } 2498 }
2601 2499
2602 double HTMLMediaElement::EffectiveMediaVolume() const { 2500 double HTMLMediaElement::EffectiveMediaVolume() const {
2603 if (muted_) 2501 if (muted_)
2604 return 0; 2502 return 0;
2605 2503
2606 return volume_; 2504 return volume_;
2607 } 2505 }
2608 2506
2609 // The spec says to fire periodic timeupdate events (those sent while playing) 2507 // The spec says to fire periodic timeupdate events (those sent while playing)
(...skipping 701 matching lines...) Expand 10 before | Expand all | Expand 10 after
3311 WebMediaPlayer::TrackId HTMLMediaElement::GetSelectedVideoTrackId() { 3209 WebMediaPlayer::TrackId HTMLMediaElement::GetSelectedVideoTrackId() {
3312 DCHECK(RuntimeEnabledFeatures::backgroundVideoTrackOptimizationEnabled()); 3210 DCHECK(RuntimeEnabledFeatures::backgroundVideoTrackOptimizationEnabled());
3313 DCHECK(HasSelectedVideoTrack()); 3211 DCHECK(HasSelectedVideoTrack());
3314 3212
3315 int selected_track_index = video_tracks_->selectedIndex(); 3213 int selected_track_index = video_tracks_->selectedIndex();
3316 VideoTrack* track = 3214 VideoTrack* track =
3317 video_tracks_->AnonymousIndexedGetter(selected_track_index); 3215 video_tracks_->AnonymousIndexedGetter(selected_track_index);
3318 return track->id(); 3216 return track->id();
3319 } 3217 }
3320 3218
3321 bool HTMLMediaElement::IsAutoplayingMuted() {
3322 if (!IsHTMLVideoElement() ||
3323 !RuntimeEnabledFeatures::autoplayMutedVideosEnabled()) {
3324 return false;
3325 }
3326
3327 return !paused() && muted() && IsLockedPendingUserGesture();
3328 }
3329
3330 void HTMLMediaElement::RequestReload(const WebURL& new_url) { 3219 void HTMLMediaElement::RequestReload(const WebURL& new_url) {
3331 DCHECK(GetWebMediaPlayer()); 3220 DCHECK(GetWebMediaPlayer());
3332 DCHECK(!src_object_); 3221 DCHECK(!src_object_);
3333 DCHECK(new_url.IsValid()); 3222 DCHECK(new_url.IsValid());
3334 DCHECK(IsSafeToLoadURL(new_url, kComplain)); 3223 DCHECK(IsSafeToLoadURL(new_url, kComplain));
3335 ResetMediaPlayerAndMediaSource(); 3224 ResetMediaPlayerAndMediaSource();
3336 StartPlayerLoad(new_url); 3225 StartPlayerLoad(new_url);
3337 } 3226 }
3338 3227
3228 bool HTMLMediaElement::IsAutoplayingMuted() {
3229 return autoplay_policy_->IsAutoplayingMuted();
3230 }
3231
3339 // MediaPlayerPresentation methods 3232 // MediaPlayerPresentation methods
3340 void HTMLMediaElement::Repaint() { 3233 void HTMLMediaElement::Repaint() {
3341 if (web_layer_) 3234 if (web_layer_)
3342 web_layer_->Invalidate(); 3235 web_layer_->Invalidate();
3343 3236
3344 UpdateDisplayState(); 3237 UpdateDisplayState();
3345 if (GetLayoutObject()) 3238 if (GetLayoutObject())
3346 GetLayoutObject()->SetShouldDoFullPaintInvalidation(); 3239 GetLayoutObject()->SetShouldDoFullPaintInvalidation();
3347 } 3240 }
3348 3241
(...skipping 577 matching lines...) Expand 10 before | Expand all | Expand 10 after
3926 visitor->Trace(video_tracks_); 3819 visitor->Trace(video_tracks_);
3927 visitor->Trace(cue_timeline_); 3820 visitor->Trace(cue_timeline_);
3928 visitor->Trace(text_tracks_); 3821 visitor->Trace(text_tracks_);
3929 visitor->Trace(text_tracks_when_resource_selection_began_); 3822 visitor->Trace(text_tracks_when_resource_selection_began_);
3930 visitor->Trace(play_promise_resolvers_); 3823 visitor->Trace(play_promise_resolvers_);
3931 visitor->Trace(play_promise_resolve_list_); 3824 visitor->Trace(play_promise_resolve_list_);
3932 visitor->Trace(play_promise_reject_list_); 3825 visitor->Trace(play_promise_reject_list_);
3933 visitor->Trace(audio_source_provider_); 3826 visitor->Trace(audio_source_provider_);
3934 visitor->Trace(autoplay_uma_helper_); 3827 visitor->Trace(autoplay_uma_helper_);
3935 visitor->Trace(src_object_); 3828 visitor->Trace(src_object_);
3936 visitor->Trace(autoplay_visibility_observer_); 3829 visitor->Trace(autoplay_policy_);
3937 visitor->Trace(media_controls_); 3830 visitor->Trace(media_controls_);
3938 visitor->Trace(controls_list_); 3831 visitor->Trace(controls_list_);
3939 visitor->template RegisterWeakMembers<HTMLMediaElement, 3832 visitor->template RegisterWeakMembers<HTMLMediaElement,
3940 &HTMLMediaElement::ClearWeakMembers>( 3833 &HTMLMediaElement::ClearWeakMembers>(
3941 this); 3834 this);
3942 Supplementable<HTMLMediaElement>::Trace(visitor); 3835 Supplementable<HTMLMediaElement>::Trace(visitor);
3943 HTMLElement::Trace(visitor); 3836 HTMLElement::Trace(visitor);
3944 SuspendableObject::Trace(visitor); 3837 SuspendableObject::Trace(visitor);
3945 } 3838 }
3946 3839
(...skipping 29 matching lines...) Expand all
3976 3869
3977 // Enable the first audio track if an audio track hasn't been enabled yet. 3870 // Enable the first audio track if an audio track hasn't been enabled yet.
3978 if (audioTracks().length() > 0 && !audioTracks().HasEnabledTrack()) 3871 if (audioTracks().length() > 0 && !audioTracks().HasEnabledTrack())
3979 audioTracks().AnonymousIndexedGetter(0)->setEnabled(true); 3872 audioTracks().AnonymousIndexedGetter(0)->setEnabled(true);
3980 3873
3981 // Select the first video track if a video track hasn't been selected yet. 3874 // Select the first video track if a video track hasn't been selected yet.
3982 if (videoTracks().length() > 0 && videoTracks().selectedIndex() == -1) 3875 if (videoTracks().length() > 0 && videoTracks().selectedIndex() == -1)
3983 videoTracks().AnonymousIndexedGetter(0)->setSelected(true); 3876 videoTracks().AnonymousIndexedGetter(0)->setSelected(true);
3984 } 3877 }
3985 3878
3986 bool HTMLMediaElement::IsLockedPendingUserGesture() const {
3987 return locked_pending_user_gesture_;
3988 }
3989
3990 void HTMLMediaElement::UnlockUserGesture() {
3991 locked_pending_user_gesture_ = false;
3992 locked_pending_user_gesture_if_cross_origin_experiment_enabled_ = false;
3993 }
3994
3995 bool HTMLMediaElement::IsGestureNeededForPlayback() const {
3996 if (!locked_pending_user_gesture_)
3997 return false;
3998
3999 return IsGestureNeededForPlaybackIfPendingUserGestureIsLocked();
4000 }
4001
4002 bool HTMLMediaElement::
4003 IsGestureNeededForPlaybackIfCrossOriginExperimentEnabled() const {
4004 if (!locked_pending_user_gesture_if_cross_origin_experiment_enabled_)
4005 return false;
4006
4007 return IsGestureNeededForPlaybackIfPendingUserGestureIsLocked();
4008 }
4009
4010 bool HTMLMediaElement::IsGestureNeededForPlaybackIfPendingUserGestureIsLocked()
4011 const {
4012 if (GetLoadType() == WebMediaPlayer::kLoadTypeMediaStream)
4013 return false;
4014
4015 // We want to allow muted video to autoplay if:
4016 // - the flag is enabled;
4017 // - Data Saver is not enabled;
4018 // - Preload was not disabled (low end devices);
4019 // - Autoplay is enabled in settings;
4020 if (IsHTMLVideoElement() && muted() &&
4021 RuntimeEnabledFeatures::autoplayMutedVideosEnabled() &&
4022 !(GetDocument().GetSettings() &&
4023 GetDocument().GetSettings()->GetDataSaverEnabled()) &&
4024 !(GetDocument().GetSettings() &&
4025 GetDocument().GetSettings()->GetForcePreloadNoneForMediaElements()) &&
4026 IsAutoplayAllowedPerSettings()) {
4027 return false;
4028 }
4029
4030 return true;
4031 }
4032
4033 bool HTMLMediaElement::IsAutoplayAllowedPerSettings() const {
4034 LocalFrame* frame = GetDocument().GetFrame();
4035 if (!frame)
4036 return false;
4037 return frame->GetContentSettingsClient()->AllowAutoplay(true);
4038 }
4039
4040 void HTMLMediaElement::SetNetworkState(NetworkState state) { 3879 void HTMLMediaElement::SetNetworkState(NetworkState state) {
4041 if (network_state_ == state) 3880 if (network_state_ == state)
4042 return; 3881 return;
4043 3882
4044 network_state_ = state; 3883 network_state_ = state;
4045 if (GetMediaControls()) 3884 if (GetMediaControls())
4046 GetMediaControls()->NetworkStateChanged(); 3885 GetMediaControls()->NetworkStateChanged();
4047 } 3886 }
4048 3887
4049 void HTMLMediaElement::VideoWillBeDrawnToCanvas() const { 3888 void HTMLMediaElement::VideoWillBeDrawnToCanvas() const {
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
4159 DEFINE_STATIC_LOCAL(EnumerationHistogram, histogram, 3998 DEFINE_STATIC_LOCAL(EnumerationHistogram, histogram,
4160 ("Media.Controls.Show.Video", kMediaControlsShowMax)); 3999 ("Media.Controls.Show.Video", kMediaControlsShowMax));
4161 return histogram; 4000 return histogram;
4162 } 4001 }
4163 4002
4164 DEFINE_STATIC_LOCAL(EnumerationHistogram, histogram, 4003 DEFINE_STATIC_LOCAL(EnumerationHistogram, histogram,
4165 ("Media.Controls.Show.Audio", kMediaControlsShowMax)); 4004 ("Media.Controls.Show.Audio", kMediaControlsShowMax));
4166 return histogram; 4005 return histogram;
4167 } 4006 }
4168 4007
4169 void HTMLMediaElement::OnVisibilityChangedForAutoplay(bool is_visible) {
4170 if (!is_visible) {
4171 if (can_autoplay_ && Autoplay()) {
4172 PauseInternal();
4173 can_autoplay_ = true;
4174 }
4175 return;
4176 }
4177
4178 if (ShouldAutoplay()) {
4179 paused_ = false;
4180 ScheduleEvent(EventTypeNames::play);
4181 ScheduleNotifyPlaying();
4182
4183 UpdatePlayState();
4184 }
4185 }
4186
4187 void HTMLMediaElement::ClearWeakMembers(Visitor* visitor) { 4008 void HTMLMediaElement::ClearWeakMembers(Visitor* visitor) {
4188 if (!ThreadHeap::IsHeapObjectAlive(audio_source_node_)) { 4009 if (!ThreadHeap::IsHeapObjectAlive(audio_source_node_)) {
4189 GetAudioSourceProvider().SetClient(nullptr); 4010 GetAudioSourceProvider().SetClient(nullptr);
4190 audio_source_node_ = nullptr; 4011 audio_source_node_ = nullptr;
4191 } 4012 }
4192 } 4013 }
4193 4014
4194 void HTMLMediaElement::AudioSourceProviderImpl::Wrap( 4015 void HTMLMediaElement::AudioSourceProviderImpl::Wrap(
4195 WebAudioSourceProvider* provider) { 4016 WebAudioSourceProvider* provider) {
4196 MutexLocker locker(provide_input_lock); 4017 MutexLocker locker(provide_input_lock);
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
4289 kMostlyFillViewportBecomeStableSeconds, BLINK_FROM_HERE); 4110 kMostlyFillViewportBecomeStableSeconds, BLINK_FROM_HERE);
4290 } 4111 }
4291 4112
4292 void HTMLMediaElement::ViewportFillDebouncerTimerFired(TimerBase*) { 4113 void HTMLMediaElement::ViewportFillDebouncerTimerFired(TimerBase*) {
4293 mostly_filling_viewport_ = true; 4114 mostly_filling_viewport_ = true;
4294 if (web_media_player_) 4115 if (web_media_player_)
4295 web_media_player_->BecameDominantVisibleContent(mostly_filling_viewport_); 4116 web_media_player_->BecameDominantVisibleContent(mostly_filling_viewport_);
4296 } 4117 }
4297 4118
4298 } // namespace blink 4119 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698