Commit 20227c09 authored by grunell@chromium.org's avatar grunell@chromium.org

Allow PeerConnection to be garbage collected after close().

* Add m_closed flag and allow gc after close().
* Assert that no calls from the client comes after close().
* Ensure no callbacks from async operation after close() is called, except getStats.
* Call stop() in the destructor.
* Add tests for garbage collected after close(), but not gc if close() is not called.
* Add tests for getStats() called after close().

BUG=373690

Review URL: https://codereview.chromium.org/329093002

git-svn-id: svn://svn.chromium.org/blink/trunk@176349 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent c8b47c1e
......@@ -3,6 +3,8 @@ Tests the RTCPeerConnection lifetime.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS observationA.wasCollected is true
PASS observationB.wasCollected is false
PASS dataChannelOpen
PASS dc.send('xyzzy'); did not throw exception.
PASS dataChannelMessage
......
......@@ -7,8 +7,6 @@
<script>
description("Tests the RTCPeerConnection lifetime.");
// This test times out if the Peer connection object is garbage collected.
var dc = null;
function dataChannelMessage(m)
......@@ -24,7 +22,7 @@ function dataChannelOpen()
shouldNotThrow("dc.send('xyzzy');");
}
function createPeerConnection()
function createPeerConnectionAndDataChannel()
{
// The Peer Connection object is leaked
var pc = new webkitRTCPeerConnection({iceServers:[]}, null);
......@@ -32,11 +30,33 @@ function createPeerConnection()
dc.onopen = dataChannelOpen;
}
createPeerConnection();
gc();
var pcB = null;
var observationB = null;
// Test that the PeerConnection object is gc'd if close is called.
var pcA = new webkitRTCPeerConnection(null, null);
var observationA = internals.observeGC(pcA);
pcA.close();
pcA = null;
asyncGC(function() {
shouldBeTrue('observationA.wasCollected');
observationA = null;
// Test that the PeerConnection object is not gc'd if close is not called.
pcB = new webkitRTCPeerConnection(null, null);
observationB = internals.observeGC(pcB);
pcB = null;
asyncGC(function() {
shouldBeFalse('observationB.wasCollected');
observationB = null;
// This test times out if the Peer connection object is garbage collected.
createPeerConnectionAndDataChannel();
gc();
});
});
window.jsTestIsAsync = true;
window.successfullyParsed = true;
</script>
</body>
</html>
......@@ -25,6 +25,22 @@ PASS res.names().indexOf("type") is >= 0
PASS res.stat("type") is "audio"
PASS status_g.namedItem(res.id) is non-null.
PASS status_g[res.id] is non-null.
PASS pc.close() did not throw exception.
PASS pc.getStats(statsHandler3) did not throw exception.
PASS statsHandler3 was called
PASS result.length is >= 2
PASS timediff is >= 0
PASS local.names().length is >= 1
PASS local.names().indexOf("type") is >= 0
PASS local.stat("type") is "audio"
PASS timediff is >= 0
PASS res.id is non-null.
PASS res.type is non-null.
PASS res.names().length is >= 1
PASS res.names().indexOf("type") is >= 0
PASS res.stat("type") is "audio"
PASS status_g.namedItem(res.id) is non-null.
PASS status_g[res.id] is non-null.
PASS successfullyParsed is true
TEST COMPLETE
......
......@@ -27,26 +27,8 @@ function error() {
finishJSTest();
}
function statsHandler1(status)
{
testPassed("statsHandler1 was called");
shouldBeNonNull('status');
result = status.result();
shouldBe('result.length', '0');
shouldNotThrow('getUserMedia({audio:true, video:true}, gotStream)');
}
function gotStream(s) {
testPassed('Got a stream.');
stream = s;
pc.addStream(stream);
shouldNotThrow('pc.getStats(statsHandler2)');
}
function statsHandler2(status)
function verifyStats(status)
{
testPassed("statsHandler2 was called");
// Status must be a global variable to be used in test statements.
status_g = status;
result = status.result();
......@@ -76,6 +58,37 @@ function statsHandler2(status)
// Named getter: Can access results by their ID values.
shouldBeNonNull('status_g.namedItem(res.id)');
shouldBeNonNull('status_g[res.id]');
}
function statsHandler1(status)
{
testPassed("statsHandler1 was called");
shouldBeNonNull('status');
result = status.result();
shouldBe('result.length', '0');
shouldNotThrow('getUserMedia({audio:true, video:true}, gotStream)');
}
function gotStream(s) {
testPassed('Got a stream.');
stream = s;
pc.addStream(stream);
shouldNotThrow('pc.getStats(statsHandler2)');
}
function statsHandler2(status)
{
testPassed("statsHandler2 was called");
verifyStats(status);
shouldNotThrow('pc.close()');
shouldNotThrow('pc.getStats(statsHandler3)');
}
function statsHandler3(status)
{
testPassed("statsHandler3 was called");
verifyStats(status);
finishJSTest();
}
......
......@@ -182,17 +182,24 @@ RTCPeerConnection::RTCPeerConnection(ExecutionContext* context, PassRefPtr<RTCCo
, m_iceConnectionState(ICEConnectionStateNew)
, m_dispatchScheduledEventRunner(this, &RTCPeerConnection::dispatchScheduledEvent)
, m_stopped(false)
, m_closed(false)
{
ScriptWrappable::init(this);
Document* document = toDocument(executionContext());
// If we fail, set |m_closed| and |m_stopped| to true, to avoid hitting the assert in the destructor.
if (!document->frame()) {
m_closed = true;
m_stopped = true;
exceptionState.throwDOMException(NotSupportedError, "PeerConnections may not be created in detached documents.");
return;
}
m_peerHandler = adoptPtr(blink::Platform::current()->createRTCPeerConnectionHandler(this));
if (!m_peerHandler) {
m_closed = true;
m_stopped = true;
exceptionState.throwDOMException(NotSupportedError, "No PeerConnection handler can be created, perhaps WebRTC is disabled?");
return;
}
......@@ -200,6 +207,8 @@ RTCPeerConnection::RTCPeerConnection(ExecutionContext* context, PassRefPtr<RTCCo
document->frame()->loader().client()->dispatchWillStartUsingPeerConnectionHandler(m_peerHandler.get());
if (!m_peerHandler->initialize(configuration, constraints)) {
m_closed = true;
m_stopped = true;
exceptionState.throwDOMException(NotSupportedError, "Failed to initialize native PeerConnection.");
return;
}
......@@ -207,9 +216,14 @@ RTCPeerConnection::RTCPeerConnection(ExecutionContext* context, PassRefPtr<RTCCo
RTCPeerConnection::~RTCPeerConnection()
{
// This checks that stop() is called if necessary before the destructor.
// We are assuming that a wrapper is always created when RTCPeerConnection is created
ASSERT(m_dataChannels.isEmpty());
// This checks that close() or stop() is called before the destructor.
// We are assuming that a wrapper is always created when RTCPeerConnection is created.
ASSERT(m_closed || m_stopped);
// FIXME: Oilpan: We can't call stop here since it touches m_dataChannels.
// Another way to ensure that data channels are stopped at RTCPeerConnection
// destruction is needed.
stop();
}
void RTCPeerConnection::createOffer(PassOwnPtr<RTCSessionDescriptionCallback> successCallback, PassOwnPtr<RTCErrorCallback> errorCallback, const Dictionary& mediaConstraints, ExceptionState& exceptionState)
......@@ -223,7 +237,7 @@ void RTCPeerConnection::createOffer(PassOwnPtr<RTCSessionDescriptionCallback> su
if (exceptionState.hadException())
return;
RefPtr<RTCSessionDescriptionRequest> request = RTCSessionDescriptionRequestImpl::create(executionContext(), successCallback, errorCallback);
RefPtr<RTCSessionDescriptionRequest> request = RTCSessionDescriptionRequestImpl::create(executionContext(), this, successCallback, errorCallback);
m_peerHandler->createOffer(request.release(), constraints);
}
......@@ -238,7 +252,7 @@ void RTCPeerConnection::createAnswer(PassOwnPtr<RTCSessionDescriptionCallback> s
if (exceptionState.hadException())
return;
RefPtr<RTCSessionDescriptionRequest> request = RTCSessionDescriptionRequestImpl::create(executionContext(), successCallback, errorCallback);
RefPtr<RTCSessionDescriptionRequest> request = RTCSessionDescriptionRequestImpl::create(executionContext(), this, successCallback, errorCallback);
m_peerHandler->createAnswer(request.release(), constraints);
}
......@@ -253,7 +267,7 @@ void RTCPeerConnection::setLocalDescription(PassRefPtrWillBeRawPtr<RTCSessionDes
return;
}
RefPtr<RTCVoidRequest> request = RTCVoidRequestImpl::create(executionContext(), successCallback, errorCallback);
RefPtr<RTCVoidRequest> request = RTCVoidRequestImpl::create(executionContext(), this, successCallback, errorCallback);
m_peerHandler->setLocalDescription(request.release(), sessionDescription->webSessionDescription());
}
......@@ -277,7 +291,7 @@ void RTCPeerConnection::setRemoteDescription(PassRefPtrWillBeRawPtr<RTCSessionDe
return;
}
RefPtr<RTCVoidRequest> request = RTCVoidRequestImpl::create(executionContext(), successCallback, errorCallback);
RefPtr<RTCVoidRequest> request = RTCVoidRequestImpl::create(executionContext(), this, successCallback, errorCallback);
m_peerHandler->setRemoteDescription(request.release(), sessionDescription->webSessionDescription());
}
......@@ -335,11 +349,12 @@ void RTCPeerConnection::addIceCandidate(RTCIceCandidate* iceCandidate, PassOwnPt
ASSERT(successCallback);
ASSERT(errorCallback);
RefPtr<RTCVoidRequest> request = RTCVoidRequestImpl::create(executionContext(), successCallback, errorCallback);
RefPtr<RTCVoidRequest> request = RTCVoidRequestImpl::create(executionContext(), this, successCallback, errorCallback);
bool implemented = m_peerHandler->addICECandidate(request.release(), iceCandidate->webCandidate());
if (!implemented)
if (!implemented) {
exceptionState.throwDOMException(NotSupportedError, "This method is not yet implemented.");
}
}
String RTCPeerConnection::signalingState() const
......@@ -474,7 +489,7 @@ MediaStream* RTCPeerConnection::getStreamById(const String& streamId)
void RTCPeerConnection::getStats(PassOwnPtr<RTCStatsCallback> successCallback, PassRefPtr<MediaStreamTrack> selector)
{
RefPtr<RTCStatsRequest> statsRequest = RTCStatsRequestImpl::create(executionContext(), successCallback, selector);
RefPtr<RTCStatsRequest> statsRequest = RTCStatsRequestImpl::create(executionContext(), this, successCallback, selector);
// FIXME: Add passing selector as part of the statsRequest.
m_peerHandler->getStats(statsRequest.release());
}
......@@ -545,6 +560,7 @@ void RTCPeerConnection::close(ExceptionState& exceptionState)
return;
m_peerHandler->stop();
m_closed = true;
changeIceConnectionState(ICEConnectionStateClosed);
changeIceGatheringState(ICEGatheringStateComplete);
......@@ -553,11 +569,13 @@ void RTCPeerConnection::close(ExceptionState& exceptionState)
void RTCPeerConnection::negotiationNeeded()
{
ASSERT(!m_closed);
scheduleDispatchEvent(Event::create(EventTypeNames::negotiationneeded));
}
void RTCPeerConnection::didGenerateICECandidate(const blink::WebRTCICECandidate& webCandidate)
{
ASSERT(!m_closed);
ASSERT(executionContext()->isContextThread());
if (webCandidate.isNull())
scheduleDispatchEvent(RTCIceCandidateEvent::create(false, false, nullptr));
......@@ -569,24 +587,28 @@ void RTCPeerConnection::didGenerateICECandidate(const blink::WebRTCICECandidate&
void RTCPeerConnection::didChangeSignalingState(SignalingState newState)
{
ASSERT(!m_closed);
ASSERT(executionContext()->isContextThread());
changeSignalingState(newState);
}
void RTCPeerConnection::didChangeICEGatheringState(ICEGatheringState newState)
{
ASSERT(!m_closed);
ASSERT(executionContext()->isContextThread());
changeIceGatheringState(newState);
}
void RTCPeerConnection::didChangeICEConnectionState(ICEConnectionState newState)
{
ASSERT(!m_closed);
ASSERT(executionContext()->isContextThread());
changeIceConnectionState(newState);
}
void RTCPeerConnection::didAddRemoteStream(const blink::WebMediaStream& remoteStream)
{
ASSERT(!m_closed);
ASSERT(executionContext()->isContextThread());
if (m_signalingState == SignalingStateClosed)
......@@ -600,6 +622,7 @@ void RTCPeerConnection::didAddRemoteStream(const blink::WebMediaStream& remoteSt
void RTCPeerConnection::didRemoveRemoteStream(const blink::WebMediaStream& remoteStream)
{
ASSERT(!m_closed);
ASSERT(executionContext()->isContextThread());
MediaStreamDescriptor* streamDescriptor = remoteStream;
......@@ -620,6 +643,7 @@ void RTCPeerConnection::didRemoveRemoteStream(const blink::WebMediaStream& remot
void RTCPeerConnection::didAddRemoteDataChannel(blink::WebRTCDataChannelHandler* handler)
{
ASSERT(!m_closed);
ASSERT(executionContext()->isContextThread());
if (m_signalingState == SignalingStateClosed)
......
......@@ -104,6 +104,10 @@ public:
void close(ExceptionState&);
// We allow getStats after close, but not other calls or callbacks.
bool shouldFireDefaultCallbacks() { return !m_closed && !m_stopped; }
bool shouldFireGetStatsCallback() { return !m_stopped; }
DEFINE_ATTRIBUTE_EVENT_LISTENER(negotiationneeded);
DEFINE_ATTRIBUTE_EVENT_LISTENER(icecandidate);
DEFINE_ATTRIBUTE_EVENT_LISTENER(signalingstatechange);
......@@ -131,7 +135,11 @@ public:
virtual void suspend() OVERRIDE;
virtual void resume() OVERRIDE;
virtual void stop() OVERRIDE;
virtual bool hasPendingActivity() const OVERRIDE { return !m_stopped; }
// We keep the this object alive until either stopped or closed.
virtual bool hasPendingActivity() const OVERRIDE
{
return !m_closed && !m_stopped;
}
virtual void trace(Visitor*) OVERRIDE;
......@@ -162,6 +170,7 @@ private:
WillBeHeapVector<RefPtrWillBeMember<Event> > m_scheduledEvents;
bool m_stopped;
bool m_closed;
};
} // namespace WebCore
......
......@@ -41,18 +41,20 @@
namespace WebCore {
PassRefPtr<RTCSessionDescriptionRequestImpl> RTCSessionDescriptionRequestImpl::create(ExecutionContext* context, PassOwnPtr<RTCSessionDescriptionCallback> successCallback, PassOwnPtr<RTCErrorCallback> errorCallback)
PassRefPtr<RTCSessionDescriptionRequestImpl> RTCSessionDescriptionRequestImpl::create(ExecutionContext* context, PassRefPtrWillBeRawPtr<RTCPeerConnection> requester, PassOwnPtr<RTCSessionDescriptionCallback> successCallback, PassOwnPtr<RTCErrorCallback> errorCallback)
{
RefPtr<RTCSessionDescriptionRequestImpl> request = adoptRef(new RTCSessionDescriptionRequestImpl(context, successCallback, errorCallback));
RefPtr<RTCSessionDescriptionRequestImpl> request = adoptRef(new RTCSessionDescriptionRequestImpl(context, requester, successCallback, errorCallback));
request->suspendIfNeeded();
return request.release();
}
RTCSessionDescriptionRequestImpl::RTCSessionDescriptionRequestImpl(ExecutionContext* context, PassOwnPtr<RTCSessionDescriptionCallback> successCallback, PassOwnPtr<RTCErrorCallback> errorCallback)
RTCSessionDescriptionRequestImpl::RTCSessionDescriptionRequestImpl(ExecutionContext* context, PassRefPtrWillBeRawPtr<RTCPeerConnection> requester, PassOwnPtr<RTCSessionDescriptionCallback> successCallback, PassOwnPtr<RTCErrorCallback> errorCallback)
: ActiveDOMObject(context)
, m_successCallback(successCallback)
, m_errorCallback(errorCallback)
, m_requester(requester)
{
ASSERT(m_requester);
}
RTCSessionDescriptionRequestImpl::~RTCSessionDescriptionRequestImpl()
......@@ -61,7 +63,8 @@ RTCSessionDescriptionRequestImpl::~RTCSessionDescriptionRequestImpl()
void RTCSessionDescriptionRequestImpl::requestSucceeded(const blink::WebRTCSessionDescription& webSessionDescription)
{
if (m_successCallback) {
bool shouldFireCallback = m_requester ? m_requester->shouldFireDefaultCallbacks() : false;
if (shouldFireCallback && m_successCallback) {
RefPtrWillBeRawPtr<RTCSessionDescription> sessionDescription = RTCSessionDescription::create(webSessionDescription);
m_successCallback->handleEvent(sessionDescription.get());
}
......@@ -71,7 +74,8 @@ void RTCSessionDescriptionRequestImpl::requestSucceeded(const blink::WebRTCSessi
void RTCSessionDescriptionRequestImpl::requestFailed(const String& error)
{
if (m_errorCallback)
bool shouldFireCallback = m_requester ? m_requester->shouldFireDefaultCallbacks() : false;
if (shouldFireCallback && m_errorCallback)
m_errorCallback->handleEvent(error);
clear();
......@@ -86,6 +90,7 @@ void RTCSessionDescriptionRequestImpl::clear()
{
m_successCallback.clear();
m_errorCallback.clear();
m_requester.clear();
}
} // namespace WebCore
......@@ -32,6 +32,7 @@
#define RTCSessionDescriptionRequestImpl_h
#include "core/dom/ActiveDOMObject.h"
#include "platform/heap/Handle.h"
#include "platform/mediastream/RTCSessionDescriptionRequest.h"
#include "wtf/PassOwnPtr.h"
#include "wtf/PassRefPtr.h"
......@@ -48,7 +49,7 @@ class RTCSessionDescriptionCallback;
class RTCSessionDescriptionRequestImpl FINAL : public RTCSessionDescriptionRequest, public ActiveDOMObject {
public:
static PassRefPtr<RTCSessionDescriptionRequestImpl> create(ExecutionContext*, PassOwnPtr<RTCSessionDescriptionCallback>, PassOwnPtr<RTCErrorCallback>);
static PassRefPtr<RTCSessionDescriptionRequestImpl> create(ExecutionContext*, PassRefPtrWillBeRawPtr<RTCPeerConnection>, PassOwnPtr<RTCSessionDescriptionCallback>, PassOwnPtr<RTCErrorCallback>);
virtual ~RTCSessionDescriptionRequestImpl();
virtual void requestSucceeded(const blink::WebRTCSessionDescription&) OVERRIDE;
......@@ -58,16 +59,16 @@ public:
virtual void stop() OVERRIDE;
private:
RTCSessionDescriptionRequestImpl(ExecutionContext*, PassOwnPtr<RTCSessionDescriptionCallback>, PassOwnPtr<RTCErrorCallback>);
RTCSessionDescriptionRequestImpl(ExecutionContext*, PassRefPtrWillBeRawPtr<RTCPeerConnection>, PassOwnPtr<RTCSessionDescriptionCallback>, PassOwnPtr<RTCErrorCallback>);
void clear();
OwnPtr<RTCSessionDescriptionCallback> m_successCallback;
OwnPtr<RTCErrorCallback> m_errorCallback;
RefPtrWillBePersistent<RTCPeerConnection> m_requester;
};
} // namespace WebCore
#endif // RTCSessionDescriptionRequestImpl_h
......@@ -27,22 +27,25 @@
#include "modules/mediastream/RTCStatsRequestImpl.h"
#include "modules/mediastream/MediaStreamTrack.h"
#include "modules/mediastream/RTCPeerConnection.h"
#include "modules/mediastream/RTCStatsCallback.h"
namespace WebCore {
PassRefPtr<RTCStatsRequestImpl> RTCStatsRequestImpl::create(ExecutionContext* context, PassOwnPtr<RTCStatsCallback> callback, PassRefPtr<MediaStreamTrack> selector)
PassRefPtr<RTCStatsRequestImpl> RTCStatsRequestImpl::create(ExecutionContext* context, PassRefPtrWillBeRawPtr<RTCPeerConnection> requester, PassOwnPtr<RTCStatsCallback> callback, PassRefPtr<MediaStreamTrack> selector)
{
RefPtr<RTCStatsRequestImpl> request = adoptRef(new RTCStatsRequestImpl(context, callback, selector));
RefPtr<RTCStatsRequestImpl> request = adoptRef(new RTCStatsRequestImpl(context, requester, callback, selector));
request->suspendIfNeeded();
return request.release();
}
RTCStatsRequestImpl::RTCStatsRequestImpl(ExecutionContext* context, PassOwnPtr<RTCStatsCallback> callback, PassRefPtr<MediaStreamTrack> selector)
RTCStatsRequestImpl::RTCStatsRequestImpl(ExecutionContext* context, PassRefPtrWillBeRawPtr<RTCPeerConnection> requester, PassOwnPtr<RTCStatsCallback> callback, PassRefPtr<MediaStreamTrack> selector)
: ActiveDOMObject(context)
, m_successCallback(callback)
, m_component(selector ? selector->component() : 0)
, m_requester(requester)
{
ASSERT(m_requester);
}
RTCStatsRequestImpl::~RTCStatsRequestImpl()
......@@ -66,9 +69,9 @@ MediaStreamComponent* RTCStatsRequestImpl::component()
void RTCStatsRequestImpl::requestSucceeded(PassRefPtrWillBeRawPtr<RTCStatsResponseBase> response)
{
if (!m_successCallback)
return;
m_successCallback->handleEvent(static_cast<RTCStatsResponse*>(response.get()));
bool shouldFireCallback = m_requester ? m_requester->shouldFireGetStatsCallback() : false;
if (shouldFireCallback && m_successCallback)
m_successCallback->handleEvent(static_cast<RTCStatsResponse*>(response.get()));
clear();
}
......@@ -80,6 +83,7 @@ void RTCStatsRequestImpl::stop()
void RTCStatsRequestImpl::clear()
{
m_successCallback.clear();
m_requester.clear();
}
} // namespace WebCore
......@@ -27,6 +27,7 @@
#include "core/dom/ActiveDOMObject.h"
#include "modules/mediastream/RTCStatsResponse.h"
#include "platform/heap/Handle.h"
#include "platform/mediastream/RTCStatsRequest.h"
#include "wtf/PassRefPtr.h"
#include "wtf/RefCounted.h"
......@@ -35,11 +36,12 @@
namespace WebCore {
class MediaStreamTrack;
class RTCPeerConnection;
class RTCStatsCallback;
class RTCStatsRequestImpl FINAL : public RTCStatsRequest, public ActiveDOMObject {
public:
static PassRefPtr<RTCStatsRequestImpl> create(ExecutionContext*, PassOwnPtr<RTCStatsCallback>, PassRefPtr<MediaStreamTrack>);
static PassRefPtr<RTCStatsRequestImpl> create(ExecutionContext*, PassRefPtrWillBeRawPtr<RTCPeerConnection>, PassOwnPtr<RTCStatsCallback>, PassRefPtr<MediaStreamTrack>);
virtual ~RTCStatsRequestImpl();
virtual PassRefPtrWillBeRawPtr<RTCStatsResponseBase> createResponse() OVERRIDE;
......@@ -52,12 +54,14 @@ public:
virtual void stop() OVERRIDE;
private:
RTCStatsRequestImpl(ExecutionContext*, PassOwnPtr<RTCStatsCallback>, PassRefPtr<MediaStreamTrack>);
RTCStatsRequestImpl(ExecutionContext*, PassRefPtrWillBeRawPtr<RTCPeerConnection>, PassOwnPtr<RTCStatsCallback>, PassRefPtr<MediaStreamTrack>);
void clear();
OwnPtr<RTCStatsCallback> m_successCallback;
RefPtr<MediaStreamComponent> m_component;
RefPtrWillBePersistent<RTCPeerConnection> m_requester;
};
} // namespace WebCore
......
......@@ -38,18 +38,20 @@
namespace WebCore {
PassRefPtr<RTCVoidRequestImpl> RTCVoidRequestImpl::create(ExecutionContext* context, PassOwnPtr<VoidCallback> successCallback, PassOwnPtr<RTCErrorCallback> errorCallback)
PassRefPtr<RTCVoidRequestImpl> RTCVoidRequestImpl::create(ExecutionContext* context, PassRefPtrWillBeRawPtr<RTCPeerConnection> requester, PassOwnPtr<VoidCallback> successCallback, PassOwnPtr<RTCErrorCallback> errorCallback)
{
RefPtr<RTCVoidRequestImpl> request = adoptRef(new RTCVoidRequestImpl(context, successCallback, errorCallback));
RefPtr<RTCVoidRequestImpl> request = adoptRef(new RTCVoidRequestImpl(context, requester, successCallback, errorCallback));
request->suspendIfNeeded();
return request.release();
}
RTCVoidRequestImpl::RTCVoidRequestImpl(ExecutionContext* context, PassOwnPtr<VoidCallback> successCallback, PassOwnPtr<RTCErrorCallback> errorCallback)
RTCVoidRequestImpl::RTCVoidRequestImpl(ExecutionContext* context, PassRefPtrWillBeRawPtr<RTCPeerConnection> requester, PassOwnPtr<VoidCallback> successCallback, PassOwnPtr<RTCErrorCallback> errorCallback)
: ActiveDOMObject(context)
, m_successCallback(successCallback)
, m_errorCallback(errorCallback)
, m_requester(requester)
{
ASSERT(m_requester);
}
RTCVoidRequestImpl::~RTCVoidRequestImpl()
......@@ -58,7 +60,8 @@ RTCVoidRequestImpl::~RTCVoidRequestImpl()
void RTCVoidRequestImpl::requestSucceeded()
{
if (m_successCallback)
bool shouldFireCallback = m_requester ? m_requester->shouldFireDefaultCallbacks() : false;
if (shouldFireCallback && m_successCallback)
m_successCallback->handleEvent();
clear();
......@@ -66,7 +69,8 @@ void RTCVoidRequestImpl::requestSucceeded()
void RTCVoidRequestImpl::requestFailed(const String& error)
{
if (m_errorCallback.get())
bool shouldFireCallback = m_requester ? m_requester->shouldFireDefaultCallbacks() : false;
if (shouldFireCallback && m_errorCallback.get())
m_errorCallback->handleEvent(error);
clear();
......@@ -81,6 +85,7 @@ void RTCVoidRequestImpl::clear()
{
m_successCallback.clear();
m_errorCallback.clear();
m_requester.clear();
}
} // namespace WebCore
......@@ -32,16 +32,18 @@
#define RTCVoidRequestImpl_h
#include "core/dom/ActiveDOMObject.h"
#include "platform/heap/Handle.h"
#include "platform/mediastream/RTCVoidRequest.h"
namespace WebCore {
class RTCErrorCallback;
class RTCPeerConnection;
class VoidCallback;
class RTCVoidRequestImpl FINAL : public RTCVoidRequest, public ActiveDOMObject {
public:
static PassRefPtr<RTCVoidRequestImpl> create(ExecutionContext*, PassOwnPtr<VoidCallback>, PassOwnPtr<RTCErrorCallback>);
static PassRefPtr<RTCVoidRequestImpl> create(ExecutionContext*, PassRefPtrWillBeRawPtr<RTCPeerConnection>, PassOwnPtr<VoidCallback>, PassOwnPtr<RTCErrorCallback>);
virtual ~RTCVoidRequestImpl();
// RTCVoidRequest
......@@ -52,16 +54,16 @@ public:
virtual void stop() OVERRIDE;
private:
RTCVoidRequestImpl(ExecutionContext*, PassOwnPtr<VoidCallback>, PassOwnPtr<RTCErrorCallback>);
RTCVoidRequestImpl(ExecutionContext*, PassRefPtrWillBeRawPtr<RTCPeerConnection>, PassOwnPtr<VoidCallback>, PassOwnPtr<RTCErrorCallback>);
void clear();
OwnPtr<VoidCallback> m_successCallback;
OwnPtr<RTCErrorCallback> m_errorCallback;
RefPtrWillBePersistent<RTCPeerConnection> m_requester;
};
} // namespace WebCore
#endif // RTCVoidRequestImpl_h
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment