Copied: branches/chromium/1271/LayoutTests/fast/mediastream/RTCPeerConnection-events-expected.txt (from rev 132420, trunk/LayoutTests/fast/mediastream/RTCPeerConnection-events-expected.txt) (0 => 132837)
--- branches/chromium/1271/LayoutTests/fast/mediastream/RTCPeerConnection-events-expected.txt (rev 0)
+++ branches/chromium/1271/LayoutTests/fast/mediastream/RTCPeerConnection-events-expected.txt 2012-10-29 19:22:49 UTC (rev 132837)
@@ -0,0 +1,15 @@
+Tests that RTCPeerConnection event callbacks are async so that for example close can be called safely. The order of the messages is very important.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS gotStream was called.
+PASS gotStream done.
+PASS onNegotiationNeeded was called.
+PASS onNegotiationNeeded done.
+PASS onStateChange was called.
+PASS pc.readyState is 'closed'
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Copied: branches/chromium/1271/LayoutTests/fast/mediastream/RTCPeerConnection-events.html (from rev 132420, trunk/LayoutTests/fast/mediastream/RTCPeerConnection-events.html) (0 => 132837)
--- branches/chromium/1271/LayoutTests/fast/mediastream/RTCPeerConnection-events.html (rev 0)
+++ branches/chromium/1271/LayoutTests/fast/mediastream/RTCPeerConnection-events.html 2012-10-29 19:22:49 UTC (rev 132837)
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script>
+description("Tests that RTCPeerConnection event callbacks are async so that for example close can be called safely. The order of the messages is very important.");
+
+var stream = null;
+var pc = null;
+
+function error() {
+ testFailed('Stream generation failed.');
+ finishJSTest();
+}
+
+function getUserMedia(dictionary, callback) {
+ try {
+ navigator.webkitGetUserMedia(dictionary, callback, error);
+ } catch (e) {
+ testFailed('webkitGetUserMedia threw exception :' + e);
+ finishJSTest();
+ }
+}
+
+function onStateChange(event) {
+ testPassed('onStateChange was called.');
+ shouldBe("pc.readyState", "'closed'");
+ finishJSTest();
+}
+
+function onNegotiationNeeded(event) {
+ testPassed('onNegotiationNeeded was called.');
+ pc._onstatechange_ = onStateChange;
+ pc.close();
+ testPassed('onNegotiationNeeded done.')
+}
+
+function gotStream(s) {
+ testPassed('gotStream was called.');
+ stream = s;
+
+ pc = new webkitRTCPeerConnection(null, null);
+ pc._onnegotiationneeded_ = onNegotiationNeeded;
+
+ pc.addStream(stream);
+ testPassed('gotStream done.');
+}
+
+getUserMedia({audio:true, video:true}, gotStream);
+
+window.jsTestIsAsync = true;
+window.successfullyParsed = true;
+
+
+</script>
+<script src=""
+</body>
+</html>
Modified: branches/chromium/1271/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp (132836 => 132837)
--- branches/chromium/1271/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp 2012-10-29 19:06:51 UTC (rev 132836)
+++ branches/chromium/1271/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp 2012-10-29 19:22:49 UTC (rev 132837)
@@ -127,6 +127,7 @@
, m_iceState(IceStateClosed)
, m_localStreams(MediaStreamList::create())
, m_remoteStreams(MediaStreamList::create())
+ , m_scheduledEventTimer(this, &RTCPeerConnection::scheduledEventTimerFired)
{
m_peerHandler = RTCPeerConnectionHandler::create(this);
if (!m_peerHandler || !m_peerHandler->initialize(configuration, constraints))
@@ -393,17 +394,17 @@
void RTCPeerConnection::negotiationNeeded()
{
- dispatchEvent(Event::create(eventNames().negotiationneededEvent, false, false));
+ scheduleDispatchEvent(Event::create(eventNames().negotiationneededEvent, false, false));
}
void RTCPeerConnection::didGenerateIceCandidate(PassRefPtr<RTCIceCandidateDescriptor> iceCandidateDescriptor)
{
ASSERT(scriptExecutionContext()->isContextThread());
if (!iceCandidateDescriptor)
- dispatchEvent(RTCIceCandidateEvent::create(false, false, 0));
+ scheduleDispatchEvent(RTCIceCandidateEvent::create(false, false, 0));
else {
RefPtr<RTCIceCandidate> iceCandidate = RTCIceCandidate::create(iceCandidateDescriptor);
- dispatchEvent(RTCIceCandidateEvent::create(false, false, iceCandidate.release()));
+ scheduleDispatchEvent(RTCIceCandidateEvent::create(false, false, iceCandidate.release()));
}
}
@@ -429,7 +430,7 @@
RefPtr<MediaStream> stream = MediaStream::create(scriptExecutionContext(), streamDescriptor);
m_remoteStreams->append(stream);
- dispatchEvent(MediaStreamEvent::create(eventNames().addstreamEvent, false, false, stream.release()));
+ scheduleDispatchEvent(MediaStreamEvent::create(eventNames().addstreamEvent, false, false, stream.release()));
}
void RTCPeerConnection::didRemoveRemoteStream(MediaStreamDescriptor* streamDescriptor)
@@ -446,7 +447,7 @@
ASSERT(m_remoteStreams->contains(stream.get()));
m_remoteStreams->remove(stream.get());
- dispatchEvent(MediaStreamEvent::create(eventNames().removestreamEvent, false, false, stream.release()));
+ scheduleDispatchEvent(MediaStreamEvent::create(eventNames().removestreamEvent, false, false, stream.release()));
}
const AtomicString& RTCPeerConnection::interfaceName() const
@@ -491,7 +492,7 @@
case ReadyStateOpening:
break;
case ReadyStateActive:
- dispatchEvent(Event::create(eventNames().openEvent, false, false));
+ scheduleDispatchEvent(Event::create(eventNames().openEvent, false, false));
break;
case ReadyStateClosing:
case ReadyStateClosed:
@@ -501,7 +502,7 @@
break;
}
- dispatchEvent(Event::create(eventNames().statechangeEvent, false, false));
+ scheduleDispatchEvent(Event::create(eventNames().statechangeEvent, false, false));
}
void RTCPeerConnection::changeIceState(IceState iceState)
@@ -510,9 +511,29 @@
return;
m_iceState = iceState;
- dispatchEvent(Event::create(eventNames().icechangeEvent, false, false));
+ scheduleDispatchEvent(Event::create(eventNames().icechangeEvent, false, false));
}
+void RTCPeerConnection::scheduleDispatchEvent(PassRefPtr<Event> event)
+{
+ m_scheduledEvents.append(event);
+
+ if (!m_scheduledEventTimer.isActive())
+ m_scheduledEventTimer.startOneShot(0);
+}
+
+void RTCPeerConnection::scheduledEventTimerFired(Timer<RTCPeerConnection>*)
+{
+ Vector<RefPtr<Event> > events;
+ events.swap(m_scheduledEvents);
+
+ Vector<RefPtr<Event> >::iterator it = events.begin();
+ for (; it != events.end(); ++it)
+ dispatchEvent((*it).release());
+
+ events.clear();
+}
+
} // namespace WebCore
#endif // ENABLE(MEDIA_STREAM)
Modified: branches/chromium/1271/Source/WebCore/Modules/mediastream/RTCPeerConnection.h (132836 => 132837)
--- branches/chromium/1271/Source/WebCore/Modules/mediastream/RTCPeerConnection.h 2012-10-29 19:06:51 UTC (rev 132836)
+++ branches/chromium/1271/Source/WebCore/Modules/mediastream/RTCPeerConnection.h 2012-10-29 19:22:49 UTC (rev 132837)
@@ -42,6 +42,7 @@
#include "RTCIceCandidate.h"
#include "RTCPeerConnectionHandler.h"
#include "RTCPeerConnectionHandlerClient.h"
+#include "Timer.h"
#include <wtf/RefCounted.h>
namespace WebCore {
@@ -116,6 +117,8 @@
RTCPeerConnection(ScriptExecutionContext*, PassRefPtr<RTCConfiguration>, PassRefPtr<MediaConstraints>, ExceptionCode&);
static PassRefPtr<RTCConfiguration> parseConfiguration(const Dictionary& configuration, ExceptionCode&);
+ void scheduleDispatchEvent(PassRefPtr<Event>);
+ void scheduledEventTimerFired(Timer<RTCPeerConnection>*);
// EventTarget implementation.
virtual EventTargetData* eventTargetData();
@@ -134,6 +137,9 @@
RefPtr<MediaStreamList> m_remoteStreams;
OwnPtr<RTCPeerConnectionHandler> m_peerHandler;
+
+ Timer<RTCPeerConnection> m_scheduledEventTimer;
+ Vector<RefPtr<Event> > m_scheduledEvents;
};
} // namespace WebCore