Bug 533840 - Don't start playback when removed from a document and autoplaying. r=padenot,cpearce
--- a/content/html/content/public/HTMLMediaElement.h
+++ b/content/html/content/public/HTMLMediaElement.h
@@ -1114,16 +1114,19 @@ protected:
bool mDownloadSuspendedByCache;
// Audio Channel Type.
AudioChannelType mAudioChannelType;
// Is this media element playing?
bool mPlayingThroughTheAudioChannel;
+ // Has this element been in a document?
+ bool mWasInDocument;
+
// An agent used to join audio channel service.
nsCOMPtr<nsIAudioChannelAgent> mAudioChannelAgent;
// List of our attached text track objects.
nsRefPtr<TextTrackList> mTextTracks;
};
} // namespace dom
--- a/content/html/content/src/HTMLMediaElement.cpp
+++ b/content/html/content/src/HTMLMediaElement.cpp
@@ -1902,17 +1902,18 @@ HTMLMediaElement::HTMLMediaElement(alrea
mHasSelfReference(false),
mShuttingDown(false),
mSuspendedForPreloadNone(false),
mMediaSecurityVerified(false),
mCORSMode(CORS_NONE),
mHasAudio(false),
mDownloadSuspendedByCache(false),
mAudioChannelType(AUDIO_CHANNEL_NORMAL),
- mPlayingThroughTheAudioChannel(false)
+ mPlayingThroughTheAudioChannel(false),
+ mWasInDocument(false)
{
#ifdef PR_LOGGING
if (!gMediaElementLog) {
gMediaElementLog = PR_NewLogModule("nsMediaElement");
}
if (!gMediaElementEventsLog) {
gMediaElementEventsLog = PR_NewLogModule("nsMediaElementEvents");
}
@@ -2323,32 +2324,35 @@ nsresult HTMLMediaElement::BindToTree(ns
if (aDocument) {
mAutoplayEnabled =
IsAutoplayEnabled() && (!aDocument || !aDocument->IsStaticDocument()) &&
!IsEditable();
// The preload action depends on the value of the autoplay attribute.
// It's value may have changed, so update it.
UpdatePreloadAction();
+ mWasInDocument = true;
+
if (aDocument->HasAudioAvailableListeners()) {
// The document already has listeners for the "MozAudioAvailable"
// event, so the decoder must be notified so it initiates
// "MozAudioAvailable" event dispatch.
NotifyAudioAvailableListener();
}
}
return rv;
}
void HTMLMediaElement::UnbindFromTree(bool aDeep,
bool aNullParent)
{
- if (!mPaused && mNetworkState != nsIDOMHTMLMediaElement::NETWORK_EMPTY)
+ if (!mPaused && mNetworkState != nsIDOMHTMLMediaElement::NETWORK_EMPTY) {
Pause();
+ }
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
}
/* static */
CanPlayStatus
HTMLMediaElement::GetCanPlay(const nsAString& aType)
{
nsContentTypeParser parser(aType);
@@ -3037,17 +3041,20 @@ void HTMLMediaElement::ChangeReadyState(
}
}
bool HTMLMediaElement::CanActivateAutoplay()
{
// For stream inputs, we activate autoplay on HAVE_CURRENT_DATA because
// this element itself might be blocking the stream from making progress by
// being paused.
+ // If we were in a document, but we have been removed, we should not start the
+ // playback.
return !mPausedForInactiveDocumentOrChannel &&
+ mWasInDocument && IsInDoc() &&
mAutoplaying &&
mPaused &&
(mDownloadSuspendedByCache ||
(mDecoder && mReadyState >= nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA) ||
(mSrcStream && mReadyState >= nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA)) &&
HasAttr(kNameSpaceID_None, nsGkAtoms::autoplay) &&
mAutoplayEnabled &&
!IsEditable();
--- a/content/media/test/Makefile.in
+++ b/content/media/test/Makefile.in
@@ -130,16 +130,17 @@ MOCHITEST_FILES = \
test_seekLies.html \
test_media_sniffer.html \
contentType.sjs \
test_streams_srcObject.html \
test_reset_src.html \
test_streams_autoplay.html \
test_streams_gc.html \
test_streams_tracks.html \
+ test_paused_after_removed.html \
$(filter disabled-for-intermittent-failures--bug-608634, test_error_in_video_document.html) \
test_texttrack.html \
test_timeupdate_small_files.html \
test_unseekable.html \
test_webvtt_disabled.html \
$(NULL)
# Disabled on Windows for frequent intermittent failures
new file mode 100644
--- /dev/null
+++ b/content/media/test/test_paused_after_removed.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=533840
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 533840</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript" src="manifest.js"></script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=533840">Mozilla Bug 533840</a>
+
+<pre id="test">
+<script class="testbody" type="text/javascript">
+ /* Test for Bug 533840 */
+
+var manager = new MediaTestManager;
+
+function onloadstart(event) {
+ var video = event.target;
+ video.parentNode.removeChild(video);
+ ok(video.paused, "Media should be paused.");
+ // wait a bit to check we won't receive the a "play" event.
+ setTimeout(function() {
+ video.removeEventListener("loadstart", onloadstart);
+ video.src = "";
+ manager.finished(video.token);
+ }, 3000);
+}
+
+function onplay(event) {
+ ok(false, "Should not receive a play event.");
+}
+
+function startTest(test, token) {
+ var video = document.createElement('video');
+ video.token = token;
+ manager.started(token);
+ video.src = test.name;
+ video.preload = "auto";
+ video.autoplay = true;
+ video.addEventListener("loadstart", onloadstart);
+ video.addEventListener("play", onplay);
+ SimpleTest.waitForExplicitFinish();
+ document.body.appendChild(video);
+}
+
+manager.runTests(gProgressTests, startTest);
+</script>
+</pre>
+</body>
+</html>
+