Diff
Modified: trunk/LayoutTests/ChangeLog (217984 => 217985)
--- trunk/LayoutTests/ChangeLog 2017-06-09 16:13:34 UTC (rev 217984)
+++ trunk/LayoutTests/ChangeLog 2017-06-09 16:14:27 UTC (rev 217985)
@@ -1,3 +1,14 @@
+2017-06-09 Eric Carlson <[email protected]>
+
+ fast/mediastream/MediaStream-page-muted.html times out and asserts
+ https://bugs.webkit.org/show_bug.cgi?id=170355
+ <rdar://problem/31376041>
+
+ Reviewed by Chris Dumez.
+
+ * fast/mediastream/media-stream-wrapper-collected-expected.txt: Added.
+ * fast/mediastream/media-stream-wrapper-collected.html: Added.
+
2017-06-09 Charlie Turner <[email protected]>
[GTK] Fix test linter reported errors
Added: trunk/LayoutTests/fast/mediastream/media-stream-wrapper-collected-expected.txt (0 => 217985)
--- trunk/LayoutTests/fast/mediastream/media-stream-wrapper-collected-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/mediastream/media-stream-wrapper-collected-expected.txt 2017-06-09 16:14:27 UTC (rev 217985)
@@ -0,0 +1,5 @@
+
+PASS Create stream
+PASS Test track
+PASS Test stream
+
Added: trunk/LayoutTests/fast/mediastream/media-stream-wrapper-collected.html (0 => 217985)
--- trunk/LayoutTests/fast/mediastream/media-stream-wrapper-collected.html (rev 0)
+++ trunk/LayoutTests/fast/mediastream/media-stream-wrapper-collected.html 2017-06-09 16:14:27 UTC (rev 217985)
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>MediaStreamTrack with event listener should not be collected.</title>
+ <script src=""
+ <script src=""
+ <script>
+
+ if (window.testRunner)
+ testRunner.setUserMediaPermission(true);
+
+ function forceGC()
+ {
+ if (window.GCController)
+ return GCController.collect();
+
+ // Force garbage collection
+ for (var ndx = 0; ndx < 99000; ndx++)
+ var str = new String("1234");
+ }
+
+ promise_test((test) => {
+ return navigator.mediaDevices.getUserMedia({ video: true })
+ .then((stream) => {
+
+ promise_test((test) => {
+ return new Promise((resolve, reject) => {
+ let track = stream.getVideoTracks()[0];
+
+ track._onmute_ = (evt) => {
+ if (window.internals)
+ internals.setMediaStreamTrackMuted(track, false);
+ }
+ track._onunmute_ = resolve;
+
+ forceGC();
+
+ if (window.internals)
+ internals.setMediaStreamTrackMuted(track, true);
+
+ setTimeout(() => reject("Track muted state did not change in .5 second"), 500);
+ });
+ }, "Test track");
+
+ promise_test((test) => {
+ return new Promise((resolve, reject) => {
+ stream._onremovetrack_ = resolve;
+
+ forceGC();
+
+ if (window.internals)
+ window.internals.removeMediaStreamTrack(stream, stream.getVideoTracks()[0]);
+
+ setTimeout(() => reject("stream.onremovetrack did not fire in .5 second"), 500);
+ });
+ }, "Test stream");
+
+ });
+ }, "Create stream");
+
+
+ </script>
+</head>
+<body>
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (217984 => 217985)
--- trunk/Source/WebCore/ChangeLog 2017-06-09 16:13:34 UTC (rev 217984)
+++ trunk/Source/WebCore/ChangeLog 2017-06-09 16:14:27 UTC (rev 217985)
@@ -1,3 +1,38 @@
+2017-06-09 Eric Carlson <[email protected]>
+
+ fast/mediastream/MediaStream-page-muted.html times out and asserts
+ https://bugs.webkit.org/show_bug.cgi?id=170355
+ <rdar://problem/31376041>
+
+ MediaStream and MediaStreamTrack need to prevent JS wrapper collection while it is possible
+ to fire an event or event listeners won't be notified.
+
+ Reviewed by Chris Dumez.
+
+ Test: fast/mediastream/media-stream-wrapper-collected.html
+
+ * Modules/mediastream/MediaStream.cpp:
+ (WebCore::MediaStream::MediaStream): Initialize ActiveDOMObject.
+ (WebCore::MediaStream::stop): New.
+ (WebCore::MediaStream::activeDOMObjectName): Ditto.
+ (WebCore::MediaStream::canSuspendForDocumentSuspension): Ditto.
+ (WebCore::MediaStream::hasPendingActivity): Ditto, prevent collection if there
+ are registered event listeners.
+ (WebCore::MediaStream::contextDestroyed): Deleted.
+ * Modules/mediastream/MediaStream.h:
+ * Modules/mediastream/MediaStream.idl:
+
+ * Modules/mediastream/MediaStreamTrack.cpp:
+ (WebCore::MediaStreamTrack::hasPendingActivity): Prevent collection if there
+ are registered event listeners.
+ * Modules/mediastream/MediaStreamTrack.h:
+
+ * testing/Internals.cpp:
+ (WebCore::Internals::removeMediaStreamTrack): stream.removeTrack doesn't generate a 'removetrack'
+ event, so call private method that does.
+ * testing/Internals.h:
+ * testing/Internals.idl:
+
2017-06-09 Daewoong Jang <[email protected]>
[cURL] Remove a call to Windows API
Modified: trunk/Source/WebCore/Modules/mediastream/MediaStream.cpp (217984 => 217985)
--- trunk/Source/WebCore/Modules/mediastream/MediaStream.cpp 2017-06-09 16:13:34 UTC (rev 217984)
+++ trunk/Source/WebCore/Modules/mediastream/MediaStream.cpp 2017-06-09 16:14:27 UTC (rev 217985)
@@ -74,7 +74,7 @@
}
MediaStream::MediaStream(ScriptExecutionContext& context, const MediaStreamTrackVector& tracks)
- : ContextDestructionObserver(&context)
+ : ActiveDOMObject(&context)
, m_private(MediaStreamPrivate::create(createTrackPrivateVector(tracks)))
, m_activityEventTimer(*this, &MediaStream::activityEventTimerFired)
, m_mediaSession(PlatformMediaSession::create(*this))
@@ -91,10 +91,11 @@
m_private->addObserver(*this);
MediaStreamRegistry::shared().registerStream(*this);
document()->addAudioProducer(this);
+ suspendIfNeeded();
}
MediaStream::MediaStream(ScriptExecutionContext& context, Ref<MediaStreamPrivate>&& streamPrivate)
- : ContextDestructionObserver(&context)
+ : ActiveDOMObject(&context)
, m_private(WTFMove(streamPrivate))
, m_activityEventTimer(*this, &MediaStream::activityEventTimerFired)
, m_mediaSession(PlatformMediaSession::create(*this))
@@ -111,6 +112,7 @@
m_trackSet.add(track->id(), WTFMove(track));
}
document()->addAudioProducer(this);
+ suspendIfNeeded();
}
MediaStream::~MediaStream()
@@ -186,11 +188,6 @@
return tracks;
}
-void MediaStream::contextDestroyed()
-{
- ContextDestructionObserver::contextDestroyed();
-}
-
void MediaStream::trackDidEnd()
{
m_private->updateActiveState(MediaStreamPrivate::NotifyClientOption::Notify);
@@ -509,6 +506,27 @@
return document() ? document()->processingUserGestureForMedia() : false;
}
+void MediaStream::stop()
+{
+ m_isActive = false;
+ endCaptureTracks();
+}
+
+const char* MediaStream::activeDOMObjectName() const
+{
+ return "MediaStream";
+}
+
+bool MediaStream::canSuspendForDocumentSuspension() const
+{
+ return !hasPendingActivity();
+}
+
+bool MediaStream::hasPendingActivity() const
+{
+ return m_isActive || !m_scheduledActivityEvents.isEmpty();
+}
+
} // namespace WebCore
#endif // ENABLE(MEDIA_STREAM)
Modified: trunk/Source/WebCore/Modules/mediastream/MediaStream.h (217984 => 217985)
--- trunk/Source/WebCore/Modules/mediastream/MediaStream.h 2017-06-09 16:13:34 UTC (rev 217984)
+++ trunk/Source/WebCore/Modules/mediastream/MediaStream.h 2017-06-09 16:14:27 UTC (rev 217985)
@@ -29,7 +29,7 @@
#if ENABLE(MEDIA_STREAM)
-#include "ContextDestructionObserver.h"
+#include "ActiveDOMObject.h"
#include "EventTarget.h"
#include "ExceptionBase.h"
#include "MediaCanStartListener.h"
@@ -51,7 +51,7 @@
class MediaStream final
: public URLRegistrable
, public EventTargetWithInlineData
- , public ContextDestructionObserver
+ , public ActiveDOMObject
, public MediaStreamTrack::Observer
, public MediaStreamPrivate::Observer
, private MediaProducer
@@ -110,15 +110,18 @@
Document* document() const;
+ // ActiveDOMObject API.
+ bool hasPendingActivity() const final;
+
+ enum class StreamModifier { DomAPI, Platform };
+ bool internalAddTrack(Ref<MediaStreamTrack>&&, StreamModifier);
+ WEBCORE_EXPORT bool internalRemoveTrack(const String&, StreamModifier);
+
protected:
MediaStream(ScriptExecutionContext&, const MediaStreamTrackVector&);
MediaStream(ScriptExecutionContext&, Ref<MediaStreamPrivate>&&);
- // ContextDestructionObserver
- void contextDestroyed() final;
-
private:
- enum class StreamModifier { DomAPI, Platform };
// EventTarget
void refEventTarget() final { ref(); }
@@ -155,8 +158,10 @@
const Document* hostingDocument() const final { return document(); }
bool processingUserGestureForMedia() const final;
- bool internalAddTrack(Ref<MediaStreamTrack>&&, StreamModifier);
- bool internalRemoveTrack(const String&, StreamModifier);
+ // ActiveDOMObject API.
+ void stop() final;
+ const char* activeDOMObjectName() const final;
+ bool canSuspendForDocumentSuspension() const final;
void scheduleActiveStateChange();
void activityEventTimerFired();
Modified: trunk/Source/WebCore/Modules/mediastream/MediaStream.idl (217984 => 217985)
--- trunk/Source/WebCore/Modules/mediastream/MediaStream.idl 2017-06-09 16:13:34 UTC (rev 217984)
+++ trunk/Source/WebCore/Modules/mediastream/MediaStream.idl 2017-06-09 16:14:27 UTC (rev 217985)
@@ -23,11 +23,13 @@
*/
[
+ ActiveDOMObject,
Conditional=MEDIA_STREAM,
Constructor,
Constructor(MediaStream stream),
Constructor(sequence<MediaStreamTrack> tracks),
ConstructorCallWith=ScriptExecutionContext,
+ ExportToWrappedFunction,
PrivateIdentifier,
PublicIdentifier
] interface MediaStream : EventTarget {
Modified: trunk/Source/WebCore/Modules/mediastream/MediaStreamTrack.cpp (217984 => 217985)
--- trunk/Source/WebCore/Modules/mediastream/MediaStreamTrack.cpp 2017-06-09 16:13:34 UTC (rev 217984)
+++ trunk/Source/WebCore/Modules/mediastream/MediaStreamTrack.cpp 2017-06-09 16:14:27 UTC (rev 217985)
@@ -348,10 +348,14 @@
bool MediaStreamTrack::canSuspendForDocumentSuspension() const
{
- // FIXME: We should try and do better here.
- return false;
+ return !hasPendingActivity();
}
+bool MediaStreamTrack::hasPendingActivity() const
+{
+ return !m_ended;
+}
+
AudioSourceProvider* MediaStreamTrack::audioSourceProvider()
{
return m_private->audioSourceProvider();
Modified: trunk/Source/WebCore/Modules/mediastream/MediaStreamTrack.h (217984 => 217985)
--- trunk/Source/WebCore/Modules/mediastream/MediaStreamTrack.h 2017-06-09 16:13:34 UTC (rev 217984)
+++ trunk/Source/WebCore/Modules/mediastream/MediaStreamTrack.h 2017-06-09 16:14:27 UTC (rev 217985)
@@ -57,7 +57,7 @@
virtual bool isCanvas() const { return false; }
const AtomicString& kind() const;
- const String& id() const;
+ WEBCORE_EXPORT const String& id() const;
const String& label() const;
bool enabled() const;
@@ -121,6 +121,9 @@
using RefCounted::ref;
using RefCounted::deref;
+ // ActiveDOMObject API.
+ bool hasPendingActivity() const final;
+
protected:
MediaStreamTrack(ScriptExecutionContext&, Ref<MediaStreamTrackPrivate>&&);
Modified: trunk/Source/WebCore/testing/Internals.cpp (217984 => 217985)
--- trunk/Source/WebCore/testing/Internals.cpp 2017-06-09 16:13:34 UTC (rev 217984)
+++ trunk/Source/WebCore/testing/Internals.cpp 2017-06-09 16:14:27 UTC (rev 217985)
@@ -195,6 +195,7 @@
#endif
#if ENABLE(MEDIA_STREAM)
+#include "MediaStream.h"
#include "MockRealtimeMediaSourceCenter.h"
#endif
@@ -4092,6 +4093,11 @@
track.source().setMuted(muted);
}
+void Internals::removeMediaStreamTrack(MediaStream& stream, MediaStreamTrack& track)
+{
+ stream.internalRemoveTrack(track.id(), MediaStream::StreamModifier::Platform);
+}
+
#endif
} // namespace WebCore
Modified: trunk/Source/WebCore/testing/Internals.h (217984 => 217985)
--- trunk/Source/WebCore/testing/Internals.h 2017-06-09 16:13:34 UTC (rev 217984)
+++ trunk/Source/WebCore/testing/Internals.h 2017-06-09 16:14:27 UTC (rev 217985)
@@ -62,6 +62,7 @@
class InternalSettings;
class MallocStatistics;
class MediaSession;
+class MediaStream;
class MediaStreamTrack;
class MemoryInfo;
class MockCDMFactory;
@@ -585,6 +586,7 @@
void grabNextMediaStreamTrackFrame(TrackFramePromise&&);
void delayMediaStreamTrackSamples(MediaStreamTrack&, float);
void setMediaStreamTrackMuted(MediaStreamTrack&, bool);
+ void removeMediaStreamTrack(MediaStream&, MediaStreamTrack&);
#endif
private:
Modified: trunk/Source/WebCore/testing/Internals.idl (217984 => 217985)
--- trunk/Source/WebCore/testing/Internals.idl 2017-06-09 16:13:34 UTC (rev 217984)
+++ trunk/Source/WebCore/testing/Internals.idl 2017-06-09 16:14:27 UTC (rev 217985)
@@ -544,4 +544,5 @@
[Conditional=MEDIA_STREAM, MayThrowException] void setMediaDeviceState(DOMString deviceID, DOMString property, boolean value);
[Conditional=MEDIA_STREAM] void delayMediaStreamTrackSamples(MediaStreamTrack track, float delay);
[Conditional=MEDIA_STREAM] void setMediaStreamTrackMuted(MediaStreamTrack track, boolean muted);
+ [Conditional=MEDIA_STREAM] void removeMediaStreamTrack(MediaStream stream, MediaStreamTrack track);
};