Bug 1513039 - part3 : remove permission request codes in MediaElement. r=cpearce
authoralwu <alwu@mozilla.com>
Mon, 07 Jan 2019 18:32:42 +0000
changeset 512755 5d5121ecc181
parent 512754 838615dbf1f3
child 512756 dba8b9714294
push id1953
push userffxbld-merge
push dateMon, 11 Mar 2019 12:10:20 +0000
treeherdermozilla-release@9c35dcbaa899 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce
bugs1513039
milestone66.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1513039 - part3 : remove permission request codes in MediaElement. r=cpearce Depends on D14326 Differential Revision: https://phabricator.services.mozilla.com/D14327
dom/html/HTMLMediaElement.cpp
dom/html/HTMLMediaElement.h
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -44,17 +44,16 @@
 #include "SVGObserverUtils.h"
 #include "TimeRanges.h"
 #include "VideoFrameContainer.h"
 #include "VideoStreamTrack.h"
 #include "base/basictypes.h"
 #include "jsapi.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/AsyncEventDispatcher.h"
-#include "mozilla/AutoplayPermissionManager.h"
 #include "mozilla/EMEUtils.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/NotNull.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Sprintf.h"
@@ -1815,20 +1814,16 @@ void HTMLMediaElement::AbortExistingLoad
       // we destroyed the decoder, so fire a timeupdate event so that the
       // change will be reflected in the controls.
       FireTimeUpdate(false);
     }
     DispatchAsyncEvent(NS_LITERAL_STRING("emptied"));
     UpdateAudioChannelPlayingState();
   }
 
-  // Disconnect requests for permission to play. We'll make a new request
-  // if required should the new media resource try to play.
-  mAutoplayPermissionRequest.DisconnectIfExists();
-
   // We may have changed mPaused, mAutoplaying, and other
   // things which can affect AddRemoveSelfReference
   AddRemoveSelfReference();
 
   mIsRunningSelectResource = false;
 
   if (mTextTrackManager) {
     mTextTrackManager->NotifyReset();
@@ -3478,17 +3473,16 @@ HTMLMediaElement::~HTMLMediaElement() {
   mShutdownObserver->Unsubscribe();
 
   if (mVideoFrameContainer) {
     mVideoFrameContainer->ForgetElement();
   }
   UnregisterActivityObserver();
 
   mSetCDMRequest.DisconnectIfExists();
-  mAutoplayPermissionRequest.DisconnectIfExists();
   if (mDecoder) {
     ShutdownDecoder();
   }
   if (mProgressTimer) {
     StopProgress();
   }
   if (mVideoDecodeSuspendTimer) {
     mVideoDecodeSuspendTimer->Cancel();
@@ -3627,71 +3621,29 @@ already_AddRefed<Promise> HTMLMediaEleme
     promise->MaybeReject(NS_ERROR_DOM_MEDIA_NOT_ALLOWED_ERR);
     DispatchEventsWhenPlayWasNotAllowed();
     return promise.forget();
   }
 
   UpdateHadAudibleAutoplayState();
 
   const bool handlingUserInput = EventStateManager::IsHandlingUserInput();
+  mPendingPlayPromises.AppendElement(promise);
+
   if (AutoplayPolicy::IsAllowedToPlay(*this)) {
-    mPendingPlayPromises.AppendElement(promise);
+    AUTOPLAY_LOG("allow MediaElement %p to play", this);
     PlayInternal(handlingUserInput);
     UpdateCustomPolicyAfterPlayed();
   } else {
-    // Prompt the user for permission to play.
-    mPendingPlayPromises.AppendElement(promise);
-    EnsureAutoplayRequested(handlingUserInput);
+    AUTOPLAY_LOG("reject MediaElement %p to play", this);
+    AsyncRejectPendingPlayPromises(NS_ERROR_DOM_MEDIA_NOT_ALLOWED_ERR);
   }
   return promise.forget();
 }
 
-void HTMLMediaElement::EnsureAutoplayRequested(bool aHandlingUserInput) {
-  if (mAutoplayPermissionRequest.Exists()) {
-    // Autoplay has already been requested in a previous play() call.
-    // Await for the previous request to be approved or denied. This
-    // play request's promise will be fulfilled with all other pending
-    // promises when the permission prompt is resolved.
-    AUTOPLAY_LOG("%p EnsureAutoplayRequested() existing request, bailing.",
-                 this);
-    return;
-  }
-
-  RefPtr<AutoplayPermissionManager> request =
-      AutoplayPolicy::RequestFor(*OwnerDoc());
-  if (!request) {
-    AsyncRejectPendingPlayPromises(NS_ERROR_DOM_INVALID_STATE_ERR);
-    return;
-  }
-  RefPtr<HTMLMediaElement> self = this;
-  request->RequestWithPrompt()
-      ->Then(mAbstractMainThread, __func__,
-             [self, handlingUserInput = aHandlingUserInput,
-              request](bool aApproved) {
-               self->mAutoplayPermissionRequest.Complete();
-               AUTOPLAY_LOG("%p Autoplay request approved request=%p",
-                            self.get(), request.get());
-               self->PlayInternal(handlingUserInput);
-               self->UpdateCustomPolicyAfterPlayed();
-             },
-             [self, request](nsresult aError) {
-               self->mAutoplayPermissionRequest.Complete();
-               AUTOPLAY_LOG("%p Autoplay request denied request=%p", self.get(),
-                            request.get());
-               LOG(LogLevel::Debug, ("%s rejecting play promises", __func__));
-               self->AsyncRejectPendingPlayPromises(
-                   NS_ERROR_DOM_MEDIA_NOT_ALLOWED_ERR);
-               nsContentUtils::ReportToConsole(
-                   nsIScriptError::warningFlag, NS_LITERAL_CSTRING("Media"),
-                   self->OwnerDoc(), nsContentUtils::eDOM_PROPERTIES,
-                   "BlockAutoplayError");
-             })
-      ->Track(mAutoplayPermissionRequest);
-}
-
 void HTMLMediaElement::DispatchEventsWhenPlayWasNotAllowed() {
   if (StaticPrefs::MediaBlockEventEnabled()) {
     DispatchAsyncEvent(NS_LITERAL_STRING("blocked"));
   }
 #if defined(MOZ_WIDGET_ANDROID)
   RefPtr<AsyncEventDispatcher> asyncDispatcher = new AsyncEventDispatcher(
       this, NS_LITERAL_STRING("MozAutoplayMediaBlocked"), CanBubble::eYes,
       ChromeOnlyDispatch::eYes);
@@ -5592,17 +5544,17 @@ bool HTMLMediaElement::CanActivateAutopl
 
 void HTMLMediaElement::CheckAutoplayDataReady() {
   if (!CanActivateAutoplay()) {
     return;
   }
 
   UpdateHadAudibleAutoplayState();
   if (!AutoplayPolicy::IsAllowedToPlay(*this)) {
-    EnsureAutoplayRequested(false);
+    DispatchEventsWhenPlayWasNotAllowed();
     return;
   }
 
   mPaused = false;
   // We changed mPaused which can affect AddRemoveSelfReference
   AddRemoveSelfReference();
   UpdateSrcMediaStreamPlaying();
   UpdateAudioChannelPlayingState();
@@ -6000,19 +5952,16 @@ void HTMLMediaElement::AddRemoveSelfRefe
           "dom::HTMLMediaElement::AddSelfReference",
           [self]() { self->mShutdownObserver->ReleaseMediaElement(); }));
     }
   }
 }
 
 void HTMLMediaElement::NotifyShutdownEvent() {
   mShuttingDown = true;
-  // Since target thread had been shutdown, it's no chance to execute the Then()
-  // afterward. Therefore, we should disconnect the request.
-  mAutoplayPermissionRequest.DisconnectIfExists();
   ResetState();
   AddRemoveSelfReference();
 }
 
 void HTMLMediaElement::DispatchAsyncSourceError(nsIContent* aSourceElement) {
   LOG_EVENT(LogLevel::Debug, ("%p Queuing simple source error event", this));
 
   nsCOMPtr<nsIRunnable> event =
@@ -7018,35 +6967,27 @@ already_AddRefed<Promise> HTMLMediaEleme
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
 
   return Promise::Create(win->AsGlobal(), aRv);
 }
 
 void HTMLMediaElement::AsyncResolvePendingPlayPromises() {
-  // Disconnect requests for permission to play. We're playing either way,
-  // so there's no point keeping the promise connected. Note: the front
-  // end permission prompt code will detect that we've started playing, and
-  // hide the permission prompt.
-  mAutoplayPermissionRequest.DisconnectIfExists();
-
   if (mShuttingDown) {
     return;
   }
 
   nsCOMPtr<nsIRunnable> event = new nsResolveOrRejectPendingPlayPromisesRunner(
       this, TakePendingPlayPromises());
 
   mMainThreadEventTarget->Dispatch(event.forget());
 }
 
 void HTMLMediaElement::AsyncRejectPendingPlayPromises(nsresult aError) {
-  mAutoplayPermissionRequest.DisconnectIfExists();
-
   if (!mPaused) {
     mPaused = true;
     DispatchAsyncEvent(NS_LITERAL_STRING("pause"));
   }
 
   if (mShuttingDown) {
     return;
   }
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -1244,19 +1244,16 @@ class HTMLMediaElement : public nsGeneri
 
   WatchManager<HTMLMediaElement> mWatchManager;
 
   // If the media element's tab has never been in the foreground, this
   // registers as with the AudioChannelAgent to notify us when the tab
   // is put in the foreground, whereupon we will begin playback.
   bool AudioChannelAgentDelayingPlayback();
 
-  // Ensures we're prompting the user for permission to autoplay.
-  void EnsureAutoplayRequested(bool aHandlingUserInput);
-
   // Update the silence range of the audio track when the audible status of
   // silent audio track changes or seeking to the new position where the audio
   // track is silent.
   void UpdateAudioTrackSilenceRange(bool aAudible);
 
   // When silent audio track becomes audible or seeking to new place, we would
   // end the current silence range and accumulate it to the total silence
   // proportion of audio track and update current silence range.
@@ -1490,20 +1487,16 @@ class HTMLMediaElement : public nsGeneri
   // Encrypted Media Extension media keys.
   RefPtr<MediaKeys> mMediaKeys;
   RefPtr<MediaKeys> mIncomingMediaKeys;
   // The dom promise is used for HTMLMediaElement::SetMediaKeys.
   RefPtr<DetailedPromise> mSetMediaKeysDOMPromise;
   // Used to indicate if the MediaKeys attaching operation is on-going or not.
   bool mAttachingMediaKey = false;
   MozPromiseRequestHolder<SetCDMPromise> mSetCDMRequest;
-  // Request holder for permission prompt to autoplay. Non-null if we're
-  // currently showing a prompt for permission to autoplay.
-  MozPromiseRequestHolder<GenericNonExclusivePromise>
-      mAutoplayPermissionRequest;
 
   // Stores the time at the start of the current 'played' range.
   double mCurrentPlayRangeStart = 1.0;
 
   // True if loadeddata has been fired.
   bool mLoadedDataFired = false;
 
   // Indicates whether current playback is a result of user action