Index: Source/modules/mediastream/RTCPeerConnection.cpp |
diff --git a/Source/modules/mediastream/RTCPeerConnection.cpp b/Source/modules/mediastream/RTCPeerConnection.cpp |
deleted file mode 100644 |
index a5e9b165b18250d19fd9ff45709a50a2e3154f8a..0000000000000000000000000000000000000000 |
--- a/Source/modules/mediastream/RTCPeerConnection.cpp |
+++ /dev/null |
@@ -1,814 +0,0 @@ |
-/* |
- * Copyright (C) 2012 Google Inc. All rights reserved. |
- * |
- * Redistribution and use in source and binary forms, with or without |
- * modification, are permitted provided that the following conditions |
- * are met: |
- * |
- * 1. Redistributions of source code must retain the above copyright |
- * notice, this list of conditions and the following disclaimer. |
- * 2. Redistributions in binary form must reproduce the above copyright |
- * notice, this list of conditions and the following disclaimer |
- * in the documentation and/or other materials provided with the |
- * distribution. |
- * 3. Neither the name of Google Inc. nor the names of its contributors |
- * may be used to endorse or promote products derived from this |
- * software without specific prior written permission. |
- * |
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
- */ |
- |
-#include "config.h" |
-#include "modules/mediastream/RTCPeerConnection.h" |
- |
-#include "bindings/core/v8/ArrayValue.h" |
-#include "bindings/core/v8/ExceptionMessages.h" |
-#include "bindings/core/v8/ExceptionState.h" |
-#include "core/dom/Document.h" |
-#include "core/dom/ExceptionCode.h" |
-#include "core/dom/ExecutionContext.h" |
-#include "core/frame/LocalFrame.h" |
-#include "core/html/VoidCallback.h" |
-#include "core/loader/FrameLoader.h" |
-#include "core/loader/FrameLoaderClient.h" |
-#include "modules/mediastream/MediaConstraintsImpl.h" |
-#include "modules/mediastream/MediaStreamEvent.h" |
-#include "modules/mediastream/RTCDTMFSender.h" |
-#include "modules/mediastream/RTCDataChannel.h" |
-#include "modules/mediastream/RTCDataChannelEvent.h" |
-#include "modules/mediastream/RTCErrorCallback.h" |
-#include "modules/mediastream/RTCIceCandidateEvent.h" |
-#include "modules/mediastream/RTCSessionDescription.h" |
-#include "modules/mediastream/RTCSessionDescriptionCallback.h" |
-#include "modules/mediastream/RTCSessionDescriptionRequestImpl.h" |
-#include "modules/mediastream/RTCStatsCallback.h" |
-#include "modules/mediastream/RTCStatsRequestImpl.h" |
-#include "modules/mediastream/RTCVoidRequestImpl.h" |
-#include "platform/mediastream/RTCConfiguration.h" |
-#include "platform/mediastream/RTCOfferOptions.h" |
-#include "public/platform/Platform.h" |
-#include "public/platform/WebMediaStream.h" |
-#include "public/platform/WebRTCConfiguration.h" |
-#include "public/platform/WebRTCDataChannelHandler.h" |
-#include "public/platform/WebRTCDataChannelInit.h" |
-#include "public/platform/WebRTCICECandidate.h" |
-#include "public/platform/WebRTCOfferOptions.h" |
-#include "public/platform/WebRTCSessionDescription.h" |
-#include "public/platform/WebRTCSessionDescriptionRequest.h" |
-#include "public/platform/WebRTCStatsRequest.h" |
-#include "public/platform/WebRTCVoidRequest.h" |
- |
-namespace blink { |
- |
-namespace { |
- |
-static bool throwExceptionIfSignalingStateClosed(RTCPeerConnection::SignalingState state, ExceptionState& exceptionState) |
-{ |
- if (state == RTCPeerConnection::SignalingStateClosed) { |
- exceptionState.throwDOMException(InvalidStateError, "The RTCPeerConnection's signalingState is 'closed'."); |
- return true; |
- } |
- |
- return false; |
-} |
- |
-} // namespace |
- |
-RTCConfiguration* RTCPeerConnection::parseConfiguration(const Dictionary& configuration, ExceptionState& exceptionState) |
-{ |
- if (configuration.isUndefinedOrNull()) |
- return 0; |
- |
- RTCIceTransports iceTransports = RTCIceTransportsAll; |
- String iceTransportsString; |
- if (DictionaryHelper::get(configuration, "iceTransports", iceTransportsString)) { |
- if (iceTransportsString == "none") { |
- iceTransports = RTCIceTransportsNone; |
- } else if (iceTransportsString == "relay") { |
- iceTransports = RTCIceTransportsRelay; |
- } else if (iceTransportsString != "all") { |
- exceptionState.throwTypeError("Malformed RTCIceTransports"); |
- return 0; |
- } |
- } |
- |
- ArrayValue iceServers; |
- bool ok = DictionaryHelper::get(configuration, "iceServers", iceServers); |
- if (!ok || iceServers.isUndefinedOrNull()) { |
- exceptionState.throwTypeError("Malformed RTCConfiguration"); |
- return 0; |
- } |
- |
- size_t numberOfServers; |
- ok = iceServers.length(numberOfServers); |
- if (!ok) { |
- exceptionState.throwTypeError("Malformed RTCConfiguration"); |
- return 0; |
- } |
- |
- RTCConfiguration* rtcConfiguration = RTCConfiguration::create(); |
- rtcConfiguration->setIceTransports(iceTransports); |
- |
- for (size_t i = 0; i < numberOfServers; ++i) { |
- Dictionary iceServer; |
- ok = iceServers.get(i, iceServer); |
- if (!ok) { |
- exceptionState.throwTypeError("Malformed RTCIceServer"); |
- return 0; |
- } |
- |
- Vector<String> names; |
- iceServer.getOwnPropertyNames(names); |
- |
- Vector<String> urlStrings; |
- if (names.contains("urls")) { |
- if (!DictionaryHelper::get(iceServer, "urls", urlStrings) || !urlStrings.size()) { |
- String urlString; |
- if (DictionaryHelper::get(iceServer, "urls", urlString)) { |
- urlStrings.append(urlString); |
- } else { |
- exceptionState.throwTypeError("Malformed RTCIceServer"); |
- return 0; |
- } |
- } |
- } else if (names.contains("url")) { |
- String urlString; |
- if (DictionaryHelper::get(iceServer, "url", urlString)) { |
- urlStrings.append(urlString); |
- } else { |
- exceptionState.throwTypeError("Malformed RTCIceServer"); |
- return 0; |
- } |
- } else { |
- exceptionState.throwTypeError("Malformed RTCIceServer"); |
- return 0; |
- } |
- |
- String username, credential; |
- DictionaryHelper::get(iceServer, "username", username); |
- DictionaryHelper::get(iceServer, "credential", credential); |
- |
- for (Vector<String>::iterator iter = urlStrings.begin(); iter != urlStrings.end(); ++iter) { |
- KURL url(KURL(), *iter); |
- if (!url.isValid() || !(url.protocolIs("turn") || url.protocolIs("turns") || url.protocolIs("stun"))) { |
- exceptionState.throwTypeError("Malformed URL"); |
- return 0; |
- } |
- |
- rtcConfiguration->appendServer(RTCIceServer::create(url, username, credential)); |
- } |
- } |
- |
- return rtcConfiguration; |
-} |
- |
-RTCOfferOptions* RTCPeerConnection::parseOfferOptions(const Dictionary& options, ExceptionState& exceptionState) |
-{ |
- if (options.isUndefinedOrNull()) |
- return 0; |
- |
- Vector<String> propertyNames; |
- options.getOwnPropertyNames(propertyNames); |
- |
- // Treat |options| as MediaConstraints if it is empty or has "optional" or "mandatory" properties for compatibility. |
- // TODO(jiayl): remove constraints when RTCOfferOptions reaches Stable and client code is ready. |
- if (propertyNames.isEmpty() || propertyNames.contains("optional") || propertyNames.contains("mandatory")) |
- return 0; |
- |
- int32_t offerToReceiveVideo = -1; |
- int32_t offerToReceiveAudio = -1; |
- bool voiceActivityDetection = true; |
- bool iceRestart = false; |
- |
- if (DictionaryHelper::get(options, "offerToReceiveVideo", offerToReceiveVideo) && offerToReceiveVideo < 0) { |
- exceptionState.throwTypeError("Invalid offerToReceiveVideo"); |
- return 0; |
- } |
- |
- if (DictionaryHelper::get(options, "offerToReceiveAudio", offerToReceiveAudio) && offerToReceiveAudio < 0) { |
- exceptionState.throwTypeError("Invalid offerToReceiveAudio"); |
- return 0; |
- } |
- |
- DictionaryHelper::get(options, "voiceActivityDetection", voiceActivityDetection); |
- DictionaryHelper::get(options, "iceRestart", iceRestart); |
- |
- RTCOfferOptions* rtcOfferOptions = RTCOfferOptions::create(offerToReceiveVideo, offerToReceiveAudio, voiceActivityDetection, iceRestart); |
- return rtcOfferOptions; |
-} |
- |
-RTCPeerConnection* RTCPeerConnection::create(ExecutionContext* context, const Dictionary& rtcConfiguration, const Dictionary& mediaConstraints, ExceptionState& exceptionState) |
-{ |
- RTCConfiguration* configuration = parseConfiguration(rtcConfiguration, exceptionState); |
- if (exceptionState.hadException()) |
- return 0; |
- |
- WebMediaConstraints constraints = MediaConstraintsImpl::create(mediaConstraints, exceptionState); |
- if (exceptionState.hadException()) |
- return 0; |
- |
- RTCPeerConnection* peerConnection = new RTCPeerConnection(context, configuration, constraints, exceptionState); |
- peerConnection->suspendIfNeeded(); |
- if (exceptionState.hadException()) |
- return 0; |
- |
- return peerConnection; |
-} |
- |
-RTCPeerConnection::RTCPeerConnection(ExecutionContext* context, RTCConfiguration* configuration, WebMediaConstraints constraints, ExceptionState& exceptionState) |
- : ActiveDOMObject(context) |
- , m_signalingState(SignalingStateStable) |
- , m_iceGatheringState(ICEGatheringStateNew) |
- , m_iceConnectionState(ICEConnectionStateNew) |
- , m_dispatchScheduledEventRunner(this, &RTCPeerConnection::dispatchScheduledEvent) |
- , m_stopped(false) |
- , m_closed(false) |
-{ |
- 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(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; |
- } |
- |
- 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; |
- } |
-} |
- |
-RTCPeerConnection::~RTCPeerConnection() |
-{ |
- // 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); |
-} |
- |
-void RTCPeerConnection::createOffer(RTCSessionDescriptionCallback* successCallback, RTCErrorCallback* errorCallback, const Dictionary& rtcOfferOptions, ExceptionState& exceptionState) |
-{ |
- if (throwExceptionIfSignalingStateClosed(m_signalingState, exceptionState)) |
- return; |
- |
- ASSERT(successCallback); |
- |
- RTCOfferOptions* offerOptions = parseOfferOptions(rtcOfferOptions, exceptionState); |
- if (exceptionState.hadException()) |
- return; |
- |
- RTCSessionDescriptionRequest* request = RTCSessionDescriptionRequestImpl::create(executionContext(), this, successCallback, errorCallback); |
- |
- if (offerOptions) { |
- m_peerHandler->createOffer(request, offerOptions); |
- } else { |
- WebMediaConstraints constraints = MediaConstraintsImpl::create(rtcOfferOptions, exceptionState); |
- if (exceptionState.hadException()) |
- return; |
- |
- m_peerHandler->createOffer(request, constraints); |
- } |
-} |
- |
-void RTCPeerConnection::createAnswer(RTCSessionDescriptionCallback* successCallback, RTCErrorCallback* errorCallback, const Dictionary& mediaConstraints, ExceptionState& exceptionState) |
-{ |
- if (throwExceptionIfSignalingStateClosed(m_signalingState, exceptionState)) |
- return; |
- |
- ASSERT(successCallback); |
- |
- WebMediaConstraints constraints = MediaConstraintsImpl::create(mediaConstraints, exceptionState); |
- if (exceptionState.hadException()) |
- return; |
- |
- RTCSessionDescriptionRequest* request = RTCSessionDescriptionRequestImpl::create(executionContext(), this, successCallback, errorCallback); |
- m_peerHandler->createAnswer(request, constraints); |
-} |
- |
-void RTCPeerConnection::setLocalDescription(RTCSessionDescription* sessionDescription, VoidCallback* successCallback, RTCErrorCallback* errorCallback, ExceptionState& exceptionState) |
-{ |
- if (throwExceptionIfSignalingStateClosed(m_signalingState, exceptionState)) |
- return; |
- |
- if (!sessionDescription) { |
- exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::argumentNullOrIncorrectType(1, "RTCSessionDescription")); |
- return; |
- } |
- |
- RTCVoidRequest* request = RTCVoidRequestImpl::create(executionContext(), this, successCallback, errorCallback); |
- m_peerHandler->setLocalDescription(request, sessionDescription->webSessionDescription()); |
-} |
- |
-RTCSessionDescription* RTCPeerConnection::localDescription(ExceptionState& exceptionState) |
-{ |
- WebRTCSessionDescription webSessionDescription = m_peerHandler->localDescription(); |
- if (webSessionDescription.isNull()) |
- return nullptr; |
- |
- return RTCSessionDescription::create(webSessionDescription); |
-} |
- |
-void RTCPeerConnection::setRemoteDescription(RTCSessionDescription* sessionDescription, VoidCallback* successCallback, RTCErrorCallback* errorCallback, ExceptionState& exceptionState) |
-{ |
- if (throwExceptionIfSignalingStateClosed(m_signalingState, exceptionState)) |
- return; |
- |
- if (!sessionDescription) { |
- exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::argumentNullOrIncorrectType(1, "RTCSessionDescription")); |
- return; |
- } |
- |
- RTCVoidRequest* request = RTCVoidRequestImpl::create(executionContext(), this, successCallback, errorCallback); |
- m_peerHandler->setRemoteDescription(request, sessionDescription->webSessionDescription()); |
-} |
- |
-RTCSessionDescription* RTCPeerConnection::remoteDescription(ExceptionState& exceptionState) |
-{ |
- WebRTCSessionDescription webSessionDescription = m_peerHandler->remoteDescription(); |
- if (webSessionDescription.isNull()) |
- return nullptr; |
- |
- return RTCSessionDescription::create(webSessionDescription); |
-} |
- |
-void RTCPeerConnection::updateIce(const Dictionary& rtcConfiguration, const Dictionary& mediaConstraints, ExceptionState& exceptionState) |
-{ |
- if (throwExceptionIfSignalingStateClosed(m_signalingState, exceptionState)) |
- return; |
- |
- RTCConfiguration* configuration = parseConfiguration(rtcConfiguration, exceptionState); |
- if (exceptionState.hadException()) |
- return; |
- |
- WebMediaConstraints constraints = MediaConstraintsImpl::create(mediaConstraints, exceptionState); |
- if (exceptionState.hadException()) |
- return; |
- |
- bool valid = m_peerHandler->updateICE(configuration, constraints); |
- if (!valid) |
- exceptionState.throwDOMException(SyntaxError, "Could not update the ICE Agent with the given configuration."); |
-} |
- |
-void RTCPeerConnection::addIceCandidate(RTCIceCandidate* iceCandidate, ExceptionState& exceptionState) |
-{ |
- if (throwExceptionIfSignalingStateClosed(m_signalingState, exceptionState)) |
- return; |
- |
- if (!iceCandidate) { |
- exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::argumentNullOrIncorrectType(1, "RTCIceCandidate")); |
- return; |
- } |
- |
- bool valid = m_peerHandler->addICECandidate(iceCandidate->webCandidate()); |
- if (!valid) |
- exceptionState.throwDOMException(SyntaxError, "The ICE candidate could not be added."); |
-} |
- |
-void RTCPeerConnection::addIceCandidate(RTCIceCandidate* iceCandidate, VoidCallback* successCallback, RTCErrorCallback* errorCallback, ExceptionState& exceptionState) |
-{ |
- if (throwExceptionIfSignalingStateClosed(m_signalingState, exceptionState)) |
- return; |
- |
- if (!iceCandidate) { |
- exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::argumentNullOrIncorrectType(1, "RTCIceCandidate")); |
- return; |
- } |
- ASSERT(successCallback); |
- ASSERT(errorCallback); |
- |
- RTCVoidRequest* request = RTCVoidRequestImpl::create(executionContext(), this, successCallback, errorCallback); |
- |
- bool implemented = m_peerHandler->addICECandidate(request, iceCandidate->webCandidate()); |
- if (!implemented) { |
- exceptionState.throwDOMException(NotSupportedError, "This method is not yet implemented."); |
- } |
-} |
- |
-String RTCPeerConnection::signalingState() const |
-{ |
- switch (m_signalingState) { |
- case SignalingStateStable: |
- return "stable"; |
- case SignalingStateHaveLocalOffer: |
- return "have-local-offer"; |
- case SignalingStateHaveRemoteOffer: |
- return "have-remote-offer"; |
- case SignalingStateHaveLocalPrAnswer: |
- return "have-local-pranswer"; |
- case SignalingStateHaveRemotePrAnswer: |
- return "have-remote-pranswer"; |
- case SignalingStateClosed: |
- return "closed"; |
- } |
- |
- ASSERT_NOT_REACHED(); |
- return String(); |
-} |
- |
-String RTCPeerConnection::iceGatheringState() const |
-{ |
- switch (m_iceGatheringState) { |
- case ICEGatheringStateNew: |
- return "new"; |
- case ICEGatheringStateGathering: |
- return "gathering"; |
- case ICEGatheringStateComplete: |
- return "complete"; |
- } |
- |
- ASSERT_NOT_REACHED(); |
- return String(); |
-} |
- |
-String RTCPeerConnection::iceConnectionState() const |
-{ |
- switch (m_iceConnectionState) { |
- case ICEConnectionStateNew: |
- return "new"; |
- case ICEConnectionStateChecking: |
- return "checking"; |
- case ICEConnectionStateConnected: |
- return "connected"; |
- case ICEConnectionStateCompleted: |
- return "completed"; |
- case ICEConnectionStateFailed: |
- return "failed"; |
- case ICEConnectionStateDisconnected: |
- return "disconnected"; |
- case ICEConnectionStateClosed: |
- return "closed"; |
- } |
- |
- ASSERT_NOT_REACHED(); |
- return String(); |
-} |
- |
-void RTCPeerConnection::addStream(MediaStream* stream, const Dictionary& mediaConstraints, ExceptionState& exceptionState) |
-{ |
- if (throwExceptionIfSignalingStateClosed(m_signalingState, exceptionState)) |
- return; |
- |
- if (!stream) { |
- exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::argumentNullOrIncorrectType(1, "MediaStream")); |
- return; |
- } |
- |
- if (m_localStreams.contains(stream)) |
- return; |
- |
- WebMediaConstraints constraints = MediaConstraintsImpl::create(mediaConstraints, exceptionState); |
- if (exceptionState.hadException()) |
- return; |
- |
- m_localStreams.append(stream); |
- |
- bool valid = m_peerHandler->addStream(stream->descriptor(), constraints); |
- if (!valid) |
- exceptionState.throwDOMException(SyntaxError, "Unable to add the provided stream."); |
-} |
- |
-void RTCPeerConnection::removeStream(MediaStream* stream, ExceptionState& exceptionState) |
-{ |
- if (throwExceptionIfSignalingStateClosed(m_signalingState, exceptionState)) |
- return; |
- |
- if (!stream) { |
- exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::argumentNullOrIncorrectType(1, "MediaStream")); |
- return; |
- } |
- |
- size_t pos = m_localStreams.find(stream); |
- if (pos == kNotFound) |
- return; |
- |
- m_localStreams.remove(pos); |
- |
- m_peerHandler->removeStream(stream->descriptor()); |
-} |
- |
-MediaStreamVector RTCPeerConnection::getLocalStreams() const |
-{ |
- return m_localStreams; |
-} |
- |
-MediaStreamVector RTCPeerConnection::getRemoteStreams() const |
-{ |
- return m_remoteStreams; |
-} |
- |
-MediaStream* RTCPeerConnection::getStreamById(const String& streamId) |
-{ |
- for (MediaStreamVector::iterator iter = m_localStreams.begin(); iter != m_localStreams.end(); ++iter) { |
- if ((*iter)->id() == streamId) |
- return iter->get(); |
- } |
- |
- for (MediaStreamVector::iterator iter = m_remoteStreams.begin(); iter != m_remoteStreams.end(); ++iter) { |
- if ((*iter)->id() == streamId) |
- return iter->get(); |
- } |
- |
- return 0; |
-} |
- |
-void RTCPeerConnection::getStats(RTCStatsCallback* successCallback, MediaStreamTrack* selector) |
-{ |
- RTCStatsRequest* statsRequest = RTCStatsRequestImpl::create(executionContext(), this, successCallback, selector); |
- // FIXME: Add passing selector as part of the statsRequest. |
- m_peerHandler->getStats(statsRequest); |
-} |
- |
-RTCDataChannel* RTCPeerConnection::createDataChannel(String label, const Dictionary& options, ExceptionState& exceptionState) |
-{ |
- if (throwExceptionIfSignalingStateClosed(m_signalingState, exceptionState)) |
- return nullptr; |
- |
- WebRTCDataChannelInit init; |
- DictionaryHelper::get(options, "ordered", init.ordered); |
- DictionaryHelper::get(options, "negotiated", init.negotiated); |
- |
- unsigned short value = 0; |
- if (DictionaryHelper::get(options, "id", value)) |
- init.id = value; |
- if (DictionaryHelper::get(options, "maxRetransmits", value)) |
- init.maxRetransmits = value; |
- if (DictionaryHelper::get(options, "maxRetransmitTime", value)) |
- init.maxRetransmitTime = value; |
- |
- String protocolString; |
- DictionaryHelper::get(options, "protocol", protocolString); |
- init.protocol = protocolString; |
- |
- RTCDataChannel* channel = RTCDataChannel::create(executionContext(), this, m_peerHandler.get(), label, init, exceptionState); |
- if (exceptionState.hadException()) |
- return nullptr; |
- m_dataChannels.append(channel); |
- return channel; |
-} |
- |
-bool RTCPeerConnection::hasLocalStreamWithTrackId(const String& trackId) |
-{ |
- for (MediaStreamVector::iterator iter = m_localStreams.begin(); iter != m_localStreams.end(); ++iter) { |
- if ((*iter)->getTrackById(trackId)) |
- return true; |
- } |
- return false; |
-} |
- |
-RTCDTMFSender* RTCPeerConnection::createDTMFSender(MediaStreamTrack* track, ExceptionState& exceptionState) |
-{ |
- if (throwExceptionIfSignalingStateClosed(m_signalingState, exceptionState)) |
- return nullptr; |
- |
- if (!track) { |
- exceptionState.throwTypeError(ExceptionMessages::argumentNullOrIncorrectType(1, "MediaStreamTrack")); |
- return nullptr; |
- } |
- |
- if (!hasLocalStreamWithTrackId(track->id())) { |
- exceptionState.throwDOMException(SyntaxError, "No local stream is available for the track provided."); |
- return nullptr; |
- } |
- |
- RTCDTMFSender* dtmfSender = RTCDTMFSender::create(executionContext(), m_peerHandler.get(), track, exceptionState); |
- if (exceptionState.hadException()) |
- return nullptr; |
- return dtmfSender; |
-} |
- |
-void RTCPeerConnection::close(ExceptionState& exceptionState) |
-{ |
- if (throwExceptionIfSignalingStateClosed(m_signalingState, exceptionState)) |
- return; |
- |
- closeInternal(); |
-} |
- |
-void RTCPeerConnection::negotiationNeeded() |
-{ |
- ASSERT(!m_closed); |
- scheduleDispatchEvent(Event::create(EventTypeNames::negotiationneeded)); |
-} |
- |
-void RTCPeerConnection::didGenerateICECandidate(const WebRTCICECandidate& webCandidate) |
-{ |
- ASSERT(!m_closed); |
- ASSERT(executionContext()->isContextThread()); |
- if (webCandidate.isNull()) |
- scheduleDispatchEvent(RTCIceCandidateEvent::create(false, false, nullptr)); |
- else { |
- RTCIceCandidate* iceCandidate = RTCIceCandidate::create(webCandidate); |
- scheduleDispatchEvent(RTCIceCandidateEvent::create(false, false, iceCandidate)); |
- } |
-} |
- |
-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 WebMediaStream& remoteStream) |
-{ |
- ASSERT(!m_closed); |
- ASSERT(executionContext()->isContextThread()); |
- |
- if (m_signalingState == SignalingStateClosed) |
- return; |
- |
- MediaStream* stream = MediaStream::create(executionContext(), remoteStream); |
- m_remoteStreams.append(stream); |
- |
- scheduleDispatchEvent(MediaStreamEvent::create(EventTypeNames::addstream, false, false, stream)); |
-} |
- |
-void RTCPeerConnection::didRemoveRemoteStream(const WebMediaStream& remoteStream) |
-{ |
- ASSERT(!m_closed); |
- ASSERT(executionContext()->isContextThread()); |
- |
- MediaStreamDescriptor* streamDescriptor = remoteStream; |
- ASSERT(streamDescriptor->client()); |
- |
- MediaStream* stream = static_cast<MediaStream*>(streamDescriptor->client()); |
- stream->streamEnded(); |
- |
- if (m_signalingState == SignalingStateClosed) |
- return; |
- |
- size_t pos = m_remoteStreams.find(stream); |
- ASSERT(pos != kNotFound); |
- m_remoteStreams.remove(pos); |
- |
- scheduleDispatchEvent(MediaStreamEvent::create(EventTypeNames::removestream, false, false, stream)); |
-} |
- |
-void RTCPeerConnection::didAddRemoteDataChannel(WebRTCDataChannelHandler* handler) |
-{ |
- ASSERT(!m_closed); |
- ASSERT(executionContext()->isContextThread()); |
- |
- if (m_signalingState == SignalingStateClosed) |
- return; |
- |
- RTCDataChannel* channel = RTCDataChannel::create(executionContext(), this, adoptPtr(handler)); |
- m_dataChannels.append(channel); |
- |
- scheduleDispatchEvent(RTCDataChannelEvent::create(EventTypeNames::datachannel, false, false, channel)); |
-} |
- |
-void RTCPeerConnection::releasePeerConnectionHandler() |
-{ |
- stop(); |
-} |
- |
-void RTCPeerConnection::closePeerConnection() |
-{ |
- ASSERT(m_signalingState != RTCPeerConnection::SignalingStateClosed); |
- closeInternal(); |
-} |
- |
-const AtomicString& RTCPeerConnection::interfaceName() const |
-{ |
- return EventTargetNames::RTCPeerConnection; |
-} |
- |
-ExecutionContext* RTCPeerConnection::executionContext() const |
-{ |
- return ActiveDOMObject::executionContext(); |
-} |
- |
-void RTCPeerConnection::suspend() |
-{ |
- m_dispatchScheduledEventRunner.suspend(); |
-} |
- |
-void RTCPeerConnection::resume() |
-{ |
- m_dispatchScheduledEventRunner.resume(); |
-} |
- |
-void RTCPeerConnection::stop() |
-{ |
- if (m_stopped) |
- return; |
- |
- m_stopped = true; |
- m_iceConnectionState = ICEConnectionStateClosed; |
- m_signalingState = SignalingStateClosed; |
- |
- HeapVector<Member<RTCDataChannel> >::iterator i = m_dataChannels.begin(); |
- for (; i != m_dataChannels.end(); ++i) |
- (*i)->stop(); |
- m_dataChannels.clear(); |
- |
- m_dispatchScheduledEventRunner.stop(); |
- |
- m_peerHandler.clear(); |
-} |
- |
-void RTCPeerConnection::changeSignalingState(SignalingState signalingState) |
-{ |
- if (m_signalingState != SignalingStateClosed && m_signalingState != signalingState) { |
- m_signalingState = signalingState; |
- scheduleDispatchEvent(Event::create(EventTypeNames::signalingstatechange)); |
- } |
-} |
- |
-void RTCPeerConnection::changeIceGatheringState(ICEGatheringState iceGatheringState) |
-{ |
- m_iceGatheringState = iceGatheringState; |
-} |
- |
-void RTCPeerConnection::changeIceConnectionState(ICEConnectionState iceConnectionState) |
-{ |
- if (m_iceConnectionState != ICEConnectionStateClosed && m_iceConnectionState != iceConnectionState) { |
- m_iceConnectionState = iceConnectionState; |
- scheduleDispatchEvent(Event::create(EventTypeNames::iceconnectionstatechange)); |
- } |
-} |
- |
-void RTCPeerConnection::closeInternal() |
-{ |
- ASSERT(m_signalingState != RTCPeerConnection::SignalingStateClosed); |
- m_peerHandler->stop(); |
- m_closed = true; |
- |
- changeIceConnectionState(ICEConnectionStateClosed); |
- changeIceGatheringState(ICEGatheringStateComplete); |
- changeSignalingState(SignalingStateClosed); |
-} |
- |
-void RTCPeerConnection::scheduleDispatchEvent(PassRefPtrWillBeRawPtr<Event> event) |
-{ |
- m_scheduledEvents.append(event); |
- |
- m_dispatchScheduledEventRunner.runAsync(); |
-} |
- |
-void RTCPeerConnection::dispatchScheduledEvent() |
-{ |
- if (m_stopped) |
- return; |
- |
- WillBeHeapVector<RefPtrWillBeMember<Event> > events; |
- events.swap(m_scheduledEvents); |
- |
- WillBeHeapVector<RefPtrWillBeMember<Event> >::iterator it = events.begin(); |
- for (; it != events.end(); ++it) |
- dispatchEvent((*it).release()); |
- |
- events.clear(); |
-} |
- |
-void RTCPeerConnection::trace(Visitor* visitor) |
-{ |
- visitor->trace(m_localStreams); |
- visitor->trace(m_remoteStreams); |
- visitor->trace(m_dataChannels); |
-#if ENABLE(OILPAN) |
- visitor->trace(m_scheduledEvents); |
-#endif |
- EventTargetWithInlineData::trace(visitor); |
-} |
- |
-} // namespace blink |