summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-08-28 15:28:34 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-08-28 13:54:51 +0000
commit2a19c63448c84c1805fb1a585c3651318bb86ca7 (patch)
treeeb17888e8531aa6ee5e85721bd553b832a7e5156 /chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
parentb014812705fc80bff0a5c120dfcef88f349816dc (diff)
downloadqtwebengine-chromium-2a19c63448c84c1805fb1a585c3651318bb86ca7.tar.gz
BASELINE: Update Chromium to 69.0.3497.70
Change-Id: I2b7b56e4e7a8b26656930def0d4575dc32b900a0 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc')
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc874
1 files changed, 620 insertions, 254 deletions
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
index 8b58d4b5d73..1506e6e6346 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
@@ -54,11 +54,10 @@
#include "third_party/blink/public/platform/web_rtc_session_description_request.h"
#include "third_party/blink/public/platform/web_rtc_stats_request.h"
#include "third_party/blink/public/platform/web_rtc_void_request.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_void_function.h"
+#include "third_party/blink/renderer/bindings/modules/v8/media_stream_track_or_string.h"
#include "third_party/blink/renderer/bindings/modules/v8/rtc_ice_candidate_init_or_rtc_ice_candidate.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_stream_track.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_certificate.h"
@@ -68,7 +67,6 @@
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/dom/dom_time_stamp.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/frame/deprecation.h"
@@ -87,11 +85,14 @@
#include "third_party/blink/renderer/modules/peerconnection/rtc_data_channel_event.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_data_channel_init.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_dtmf_sender.h"
+#include "third_party/blink/renderer/modules/peerconnection/rtc_error_util.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_ice_server.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_offer_options.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_ice_event.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.h"
+#include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.h"
+#include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_init.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_session_description.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_session_description_init.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_session_description_request_impl.h"
@@ -103,6 +104,7 @@
#include "third_party/blink/renderer/modules/peerconnection/rtc_void_request_promise_impl.h"
#include "third_party/blink/renderer/modules/peerconnection/testing/internals_rtc_peer_connection.h"
#include "third_party/blink/renderer/modules/peerconnection/web_rtc_stats_report_callback_resolver.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/microtask.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
@@ -120,15 +122,20 @@ const char kSignalingStateClosedMessage[] =
"The RTCPeerConnection's signalingState is 'closed'.";
const char kModifiedSdpMessage[] =
"The SDP does not match the previously generated SDP for this type";
+const char kOnlySupportedInUnifiedPlanMessage[] =
+ "This operation is only supported in 'unified-plan'. 'unified-plan' will "
+ "become the default behavior in the future, but it is currently "
+ "experimental. To try it out, construct the RTCPeerConnection with "
+ "sdpSemantics:'unified-plan' present in the RTCConfiguration argument.";
// The maximum number of PeerConnections that can exist simultaneously.
const long kMaxPeerConnections = 500;
bool ThrowExceptionIfSignalingStateClosed(
- RTCPeerConnection::SignalingState state,
+ webrtc::PeerConnectionInterface::SignalingState state,
ExceptionState& exception_state) {
- if (state == RTCPeerConnection::kSignalingStateClosed) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ if (state == webrtc::PeerConnectionInterface::SignalingState::kClosed) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
kSignalingStateClosedMessage);
return true;
}
@@ -147,14 +154,15 @@ void AsyncCallErrorCallback(V8RTCPeerConnectionErrorCallback* error_callback,
}
bool CallErrorCallbackIfSignalingStateClosed(
- RTCPeerConnection::SignalingState state,
+ webrtc::PeerConnectionInterface::SignalingState state,
V8RTCPeerConnectionErrorCallback* error_callback) {
- if (state == RTCPeerConnection::kSignalingStateClosed) {
- if (error_callback)
+ if (state == webrtc::PeerConnectionInterface::SignalingState::kClosed) {
+ if (error_callback) {
AsyncCallErrorCallback(
- error_callback, DOMException::Create(kInvalidStateError,
- kSignalingStateClosedMessage));
-
+ error_callback,
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kSignalingStateClosedMessage));
+ }
return true;
}
@@ -329,23 +337,26 @@ WebRTCConfiguration ParseConfiguration(ExecutionContext* context,
KURL url(NullURL(), url_string);
if (!url.IsValid()) {
exception_state.ThrowDOMException(
- kSyntaxError, "'" + url_string + "' is not a valid URL.");
+ DOMExceptionCode::kSyntaxError,
+ "'" + url_string + "' is not a valid URL.");
return WebRTCConfiguration();
}
if (!(url.ProtocolIs("turn") || url.ProtocolIs("turns") ||
url.ProtocolIs("stun"))) {
exception_state.ThrowDOMException(
- kSyntaxError, "'" + url.Protocol() +
- "' is not one of the supported URL schemes "
- "'stun', 'turn' or 'turns'.");
+ DOMExceptionCode::kSyntaxError,
+ "'" + url.Protocol() +
+ "' is not one of the supported URL schemes "
+ "'stun', 'turn' or 'turns'.");
return WebRTCConfiguration();
}
if ((url.ProtocolIs("turn") || url.ProtocolIs("turns")) &&
(username.IsNull() || credential.IsNull())) {
- exception_state.ThrowDOMException(kInvalidAccessError,
- "Both username and credential are "
- "required when the URL scheme is "
- "\"turn\" or \"turns\".");
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidAccessError,
+ "Both username and credential are "
+ "required when the URL scheme is "
+ "\"turn\" or \"turns\".");
}
ice_servers.push_back(WebRTCIceServer{url, username, credential});
}
@@ -484,11 +495,6 @@ RTCPeerConnection* RTCPeerConnection::Create(
ParseConfiguration(context, rtc_configuration, exception_state);
if (exception_state.HadException())
return nullptr;
- // Override default SDP semantics if RuntimeEnabled=RTCUnifiedPlanByDefault.
- if (!rtc_configuration.hasSdpSemantics() &&
- RuntimeEnabledFeatures::RTCUnifiedPlanByDefaultEnabled()) {
- configuration.sdp_semantics = WebRTCSdpSemantics::kUnifiedPlan;
- }
// Make sure no certificates have expired.
if (configuration.certificates.size() > 0) {
@@ -497,7 +503,7 @@ RTCPeerConnection* RTCPeerConnection::Create(
configuration.certificates) {
DOMTimeStamp expires = certificate->Expires();
if (expires <= now) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"Expired certificate(s).");
return nullptr;
}
@@ -513,7 +519,7 @@ RTCPeerConnection* RTCPeerConnection::Create(
}
RTCPeerConnection* peer_connection = new RTCPeerConnection(
- context, configuration, constraints, exception_state);
+ context, std::move(configuration), constraints, exception_state);
peer_connection->PauseIfNeeded();
if (exception_state.HadException())
return nullptr;
@@ -522,11 +528,12 @@ RTCPeerConnection* RTCPeerConnection::Create(
}
RTCPeerConnection::RTCPeerConnection(ExecutionContext* context,
- const WebRTCConfiguration& configuration,
+ WebRTCConfiguration configuration,
WebMediaConstraints constraints,
ExceptionState& exception_state)
: PausableObject(context),
- signaling_state_(kSignalingStateStable),
+ signaling_state_(
+ webrtc::PeerConnectionInterface::SignalingState::kStable),
ice_gathering_state_(kICEGatheringStateNew),
ice_connection_state_(kICEConnectionStateNew),
// WebRTC spec specifies kNetworking as task source.
@@ -541,6 +548,24 @@ RTCPeerConnection::RTCPeerConnection(ExecutionContext* context,
closed_(false),
has_data_channels_(false),
sdp_semantics_(configuration.sdp_semantics) {
+ // The original SDP semantics value is the value passed in by the caller,
+ // which if not specified has the value "kDefault". For |sdp_semantics_| this
+ // is translated to the actual SDP semantics used ("kPlanB" or
+ // "kUnifiedPlan"), but for the sake of UMA use counters it is of interest to
+ // know if the caller did not explicitly set it.
+ WebRTCSdpSemantics original_sdp_semantics_value = sdp_semantics_;
+ if (sdp_semantics_ == WebRTCSdpSemantics::kDefault) {
+ if (!RuntimeEnabledFeatures::RTCUnifiedPlanByDefaultEnabled()) {
+ // By default: The default SDP semantics is: "kPlanB".
+ sdp_semantics_ = configuration.sdp_semantics = WebRTCSdpSemantics::kPlanB;
+ } else {
+ // Override default SDP semantics to "kUnifiedPlan" with
+ // RuntimeEnabled=RTCUnifiedPlanByDefault.
+ sdp_semantics_ = configuration.sdp_semantics =
+ WebRTCSdpSemantics::kUnifiedPlan;
+ }
+ }
+
Document* document = ToDocument(GetExecutionContext());
InstanceCounters::IncrementCounter(
@@ -551,7 +576,7 @@ RTCPeerConnection::RTCPeerConnection(ExecutionContext* context,
InstanceCounters::kRTCPeerConnectionCounter) > kMaxPeerConnections) {
closed_ = true;
stopped_ = true;
- exception_state.ThrowDOMException(kUnknownError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kUnknownError,
"Cannot create so many PeerConnections");
return;
}
@@ -559,7 +584,7 @@ RTCPeerConnection::RTCPeerConnection(ExecutionContext* context,
closed_ = true;
stopped_ = true;
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"PeerConnections may not be created in detached documents.");
return;
}
@@ -569,7 +594,7 @@ RTCPeerConnection::RTCPeerConnection(ExecutionContext* context,
if (!peer_handler_) {
closed_ = true;
stopped_ = true;
- exception_state.ThrowDOMException(kNotSupportedError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"No PeerConnection handler can be "
"created, perhaps WebRTC is disabled?");
return;
@@ -578,11 +603,13 @@ RTCPeerConnection::RTCPeerConnection(ExecutionContext* context,
document->GetFrame()->Client()->DispatchWillStartUsingPeerConnectionHandler(
peer_handler_.get());
- if (!peer_handler_->Initialize(configuration, constraints)) {
+ if (!peer_handler_->Initialize(configuration, constraints,
+ original_sdp_semantics_value)) {
closed_ = true;
stopped_ = true;
exception_state.ThrowDOMException(
- kNotSupportedError, "Failed to initialize native PeerConnection.");
+ DOMExceptionCode::kNotSupportedError,
+ "Failed to initialize native PeerConnection.");
return;
}
@@ -609,15 +636,18 @@ void RTCPeerConnection::Dispose() {
ScriptPromise RTCPeerConnection::createOffer(ScriptState* script_state,
const RTCOfferOptions& options) {
- if (signaling_state_ == kSignalingStateClosed)
+ if (signaling_state_ ==
+ webrtc::PeerConnectionInterface::SignalingState::kClosed) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kInvalidStateError, kSignalingStateClosedMessage));
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kSignalingStateClosedMessage));
+ }
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
ScriptPromise promise = resolver->Promise();
RTCSessionDescriptionRequest* request =
- RTCSessionDescriptionRequestPromiseImpl::Create(this, resolver);
+ RTCSessionDescriptionRequestPromiseImpl::Create(
+ this, resolver, "RTCPeerConnection", "createOffer");
if (options.hasOfferToReceiveAudio() || options.hasOfferToReceiveVideo()) {
ExecutionContext* context = ExecutionContext::From(script_state);
UseCounter::Count(
@@ -670,8 +700,9 @@ ScriptPromise RTCPeerConnection::createOffer(
// WebIDL.
if (media_error_state.CanGenerateException()) {
String error_msg = media_error_state.GetErrorMessage();
- AsyncCallErrorCallback(error_callback,
- DOMException::Create(kOperationError, error_msg));
+ AsyncCallErrorCallback(
+ error_callback,
+ DOMException::Create(DOMExceptionCode::kOperationError, error_msg));
return ScriptPromise::CastUndefined(script_state);
}
@@ -691,15 +722,18 @@ ScriptPromise RTCPeerConnection::createOffer(
ScriptPromise RTCPeerConnection::createAnswer(ScriptState* script_state,
const RTCAnswerOptions& options) {
- if (signaling_state_ == kSignalingStateClosed)
+ if (signaling_state_ ==
+ webrtc::PeerConnectionInterface::SignalingState::kClosed) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kInvalidStateError, kSignalingStateClosedMessage));
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kSignalingStateClosedMessage));
+ }
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
ScriptPromise promise = resolver->Promise();
RTCSessionDescriptionRequest* request =
- RTCSessionDescriptionRequestPromiseImpl::Create(this, resolver);
+ RTCSessionDescriptionRequestPromiseImpl::Create(
+ this, resolver, "RTCPeerConnection", "createAnswer");
peer_handler_->CreateAnswer(request, ConvertToWebRTCAnswerOptions(options));
return promise;
}
@@ -733,8 +767,9 @@ ScriptPromise RTCPeerConnection::createAnswer(
// WebIDL.
if (media_error_state.CanGenerateException()) {
String error_msg = media_error_state.GetErrorMessage();
- AsyncCallErrorCallback(error_callback,
- DOMException::Create(kOperationError, error_msg));
+ AsyncCallErrorCallback(
+ error_callback,
+ DOMException::Create(DOMExceptionCode::kOperationError, error_msg));
return ScriptPromise::CastUndefined(script_state);
}
@@ -749,8 +784,9 @@ DOMException* RTCPeerConnection::checkSdpForStateErrors(
ExecutionContext* context,
const RTCSessionDescriptionInit& session_description_init,
String* sdp) {
- if (signaling_state_ == kSignalingStateClosed) {
- return DOMException::Create(kInvalidStateError,
+ if (signaling_state_ ==
+ webrtc::PeerConnectionInterface::SignalingState::kClosed) {
+ return DOMException::Create(DOMExceptionCode::kInvalidStateError,
kSignalingStateClosedMessage);
}
@@ -760,7 +796,7 @@ DOMException* RTCPeerConnection::checkSdpForStateErrors(
*sdp = last_offer_;
} else if (session_description_init.sdp() != last_offer_) {
if (FingerprintMismatch(last_offer_, *sdp)) {
- return DOMException::Create(kInvalidModificationError,
+ return DOMException::Create(DOMExceptionCode::kInvalidModificationError,
kModifiedSdpMessage);
} else {
UseCounter::Count(context, WebFeature::kRTCLocalSdpModification);
@@ -774,7 +810,7 @@ DOMException* RTCPeerConnection::checkSdpForStateErrors(
*sdp = last_answer_;
} else if (session_description_init.sdp() != last_answer_) {
if (FingerprintMismatch(last_answer_, *sdp)) {
- return DOMException::Create(kInvalidModificationError,
+ return DOMException::Create(DOMExceptionCode::kInvalidModificationError,
kModifiedSdpMessage);
} else {
UseCounter::Count(context, WebFeature::kRTCLocalSdpModification);
@@ -797,7 +833,8 @@ ScriptPromise RTCPeerConnection::setLocalDescription(
}
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
ScriptPromise promise = resolver->Promise();
- RTCVoidRequest* request = RTCVoidRequestPromiseImpl::Create(this, resolver);
+ RTCVoidRequest* request = RTCVoidRequestPromiseImpl::Create(
+ this, resolver, "RTCPeerConnection", "setLocalDescription");
peer_handler_->SetLocalDescription(
request, WebRTCSessionDescription(session_description_init.type(), sdp));
return promise;
@@ -855,14 +892,17 @@ RTCSessionDescription* RTCPeerConnection::localDescription() {
ScriptPromise RTCPeerConnection::setRemoteDescription(
ScriptState* script_state,
const RTCSessionDescriptionInit& session_description_init) {
- if (signaling_state_ == kSignalingStateClosed)
+ if (signaling_state_ ==
+ webrtc::PeerConnectionInterface::SignalingState::kClosed) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kInvalidStateError, kSignalingStateClosedMessage));
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kSignalingStateClosedMessage));
+ }
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
ScriptPromise promise = resolver->Promise();
- RTCVoidRequest* request = RTCVoidRequestPromiseImpl::Create(this, resolver);
+ RTCVoidRequest* request = RTCVoidRequestPromiseImpl::Create(
+ this, resolver, "RTCPeerConnection", "setRemoteDescription");
peer_handler_->SetRemoteDescription(
request, WebRTCSessionDescription(session_description_init.type(),
session_description_init.sdp()));
@@ -921,6 +961,12 @@ void RTCPeerConnection::setConfiguration(
WebRTCConfiguration configuration = ParseConfiguration(
ExecutionContext::From(script_state), rtc_configuration, exception_state);
+ // Overwrite "kDefault" with |sdp_semantics_| as set in the constructor to
+ // avoid duplicate logic for interpreting the default and SetConfiguration()
+ // failing if different layers have different notions of default.
+ if (configuration.sdp_semantics == blink::WebRTCSdpSemantics::kDefault) {
+ configuration.sdp_semantics = sdp_semantics_;
+ }
if (exception_state.HadException())
return;
@@ -936,12 +982,12 @@ void RTCPeerConnection::setConfiguration(
// All errors besides InvalidModification should have been detected above.
if (error == webrtc::RTCErrorType::INVALID_MODIFICATION) {
exception_state.ThrowDOMException(
- kInvalidModificationError,
+ DOMExceptionCode::kInvalidModificationError,
"Attempted to modify the PeerConnection's "
"configuration in an unsupported way.");
} else {
exception_state.ThrowDOMException(
- kOperationError,
+ DOMExceptionCode::kOperationError,
"Could not update the PeerConnection with the given configuration.");
}
}
@@ -1011,8 +1057,9 @@ ScriptPromise RTCPeerConnection::generateCertificate(
WebRTCKeyParams::CreateRSA(modulus_length, public_exponent);
} else {
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kNotSupportedError,
- unsupported_params_string));
+ script_state,
+ DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ unsupported_params_string));
}
break;
case kWebCryptoAlgorithmIdEcdsa:
@@ -1023,16 +1070,18 @@ ScriptPromise RTCPeerConnection::generateCertificate(
key_params = WebRTCKeyParams::CreateECDSA(kWebRTCECCurveNistP256);
} else {
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kNotSupportedError,
- unsupported_params_string));
+ script_state,
+ DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ unsupported_params_string));
}
break;
default:
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kNotSupportedError,
- "The 1st argument provided is an "
- "AlgorithmIdentifier, but the "
- "algorithm is not supported."));
+ script_state,
+ DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ "The 1st argument provided is an "
+ "AlgorithmIdentifier, but the "
+ "algorithm is not supported."));
break;
}
DCHECK(key_params.has_value());
@@ -1044,8 +1093,8 @@ ScriptPromise RTCPeerConnection::generateCertificate(
// generator support these parameters?
if (!certificate_generator->IsSupportedKeyParams(key_params.value())) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kNotSupportedError, unsupported_params_string));
+ script_state, DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ unsupported_params_string));
}
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
@@ -1074,29 +1123,34 @@ ScriptPromise RTCPeerConnection::generateCertificate(
ScriptPromise RTCPeerConnection::addIceCandidate(
ScriptState* script_state,
- const RTCIceCandidateInitOrRTCIceCandidate& candidate) {
- if (signaling_state_ == kSignalingStateClosed)
+ const RTCIceCandidateInitOrRTCIceCandidate& candidate,
+ ExceptionState& exception_state) {
+ if (signaling_state_ ==
+ webrtc::PeerConnectionInterface::SignalingState::kClosed) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kInvalidStateError, kSignalingStateClosedMessage));
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kSignalingStateClosedMessage));
+ }
- if (IsIceCandidateMissingSdp(candidate))
- return ScriptPromise::Reject(
- script_state,
- V8ThrowException::CreateTypeError(
- script_state->GetIsolate(),
- "Candidate missing values for both sdpMid and sdpMLineIndex"));
+ if (IsIceCandidateMissingSdp(candidate)) {
+ exception_state.ThrowTypeError(
+ "Candidate missing values for both sdpMid and sdpMLineIndex");
+ return ScriptPromise();
+ }
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
ScriptPromise promise = resolver->Promise();
- RTCVoidRequest* request = RTCVoidRequestPromiseImpl::Create(this, resolver);
+ RTCVoidRequest* request = RTCVoidRequestPromiseImpl::Create(
+ this, resolver, "RTCPeerConnection", "addIceCandidate");
scoped_refptr<WebRTCICECandidate> web_candidate = ConvertToWebRTCIceCandidate(
ExecutionContext::From(script_state), candidate);
bool implemented =
peer_handler_->AddICECandidate(request, std::move(web_candidate));
- if (!implemented)
- resolver->Reject(DOMException::Create(
- kOperationError, "This operation could not be completed."));
+ if (!implemented) {
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kOperationError,
+ "This operation could not be completed."));
+ }
return promise;
}
@@ -1105,19 +1159,19 @@ ScriptPromise RTCPeerConnection::addIceCandidate(
ScriptState* script_state,
const RTCIceCandidateInitOrRTCIceCandidate& candidate,
V8VoidFunction* success_callback,
- V8RTCPeerConnectionErrorCallback* error_callback) {
+ V8RTCPeerConnectionErrorCallback* error_callback,
+ ExceptionState& exception_state) {
DCHECK(success_callback);
DCHECK(error_callback);
if (CallErrorCallbackIfSignalingStateClosed(signaling_state_, error_callback))
return ScriptPromise::CastUndefined(script_state);
- if (IsIceCandidateMissingSdp(candidate))
- return ScriptPromise::Reject(
- script_state,
- V8ThrowException::CreateTypeError(
- script_state->GetIsolate(),
- "Candidate missing values for both sdpMid and sdpMLineIndex"));
+ if (IsIceCandidateMissingSdp(candidate)) {
+ exception_state.ThrowTypeError(
+ "Candidate missing values for both sdpMid and sdpMLineIndex");
+ return ScriptPromise();
+ }
RTCVoidRequest* request = RTCVoidRequestImpl::Create(
GetExecutionContext(), this, success_callback, error_callback);
@@ -1128,7 +1182,7 @@ ScriptPromise RTCPeerConnection::addIceCandidate(
if (!implemented)
AsyncCallErrorCallback(
error_callback,
- DOMException::Create(kOperationError,
+ DOMException::Create(DOMExceptionCode::kOperationError,
"This operation could not be completed."));
return ScriptPromise::CastUndefined(script_state);
@@ -1136,17 +1190,17 @@ ScriptPromise RTCPeerConnection::addIceCandidate(
String RTCPeerConnection::signalingState() const {
switch (signaling_state_) {
- case kSignalingStateStable:
+ case webrtc::PeerConnectionInterface::SignalingState::kStable:
return "stable";
- case kSignalingStateHaveLocalOffer:
+ case webrtc::PeerConnectionInterface::SignalingState::kHaveLocalOffer:
return "have-local-offer";
- case kSignalingStateHaveRemoteOffer:
+ case webrtc::PeerConnectionInterface::SignalingState::kHaveRemoteOffer:
return "have-remote-offer";
- case kSignalingStateHaveLocalPrAnswer:
+ case webrtc::PeerConnectionInterface::SignalingState::kHaveLocalPrAnswer:
return "have-local-pranswer";
- case kSignalingStateHaveRemotePrAnswer:
+ case webrtc::PeerConnectionInterface::SignalingState::kHaveRemotePrAnswer:
return "have-remote-pranswer";
- case kSignalingStateClosed:
+ case webrtc::PeerConnectionInterface::SignalingState::kClosed:
return "closed";
}
@@ -1235,17 +1289,28 @@ void RTCPeerConnection::removeStream(MediaStream* stream,
}
String RTCPeerConnection::id(ScriptState* script_state) const {
- DCHECK(OriginTrials::rtcPeerConnectionIdEnabled(
+ DCHECK(OriginTrials::RtcPeerConnectionIdEnabled(
ExecutionContext::From(script_state)));
return peer_handler_->Id();
}
MediaStreamVector RTCPeerConnection::getLocalStreams() const {
MediaStreamVector local_streams;
- for (const auto& rtp_sender : getSenders()) {
- for (const auto& stream : rtp_sender->streams()) {
- if (!local_streams.Contains(stream))
- local_streams.push_back(stream);
+ if (sdp_semantics_ == WebRTCSdpSemantics::kPlanB) {
+ for (const auto& sender : rtp_senders_) {
+ for (const auto& stream : sender->streams()) {
+ if (!local_streams.Contains(stream))
+ local_streams.push_back(stream);
+ }
+ }
+ } else {
+ for (const auto& transceiver : transceivers_) {
+ if (!transceiver->DirectionHasSend())
+ continue;
+ for (const auto& stream : transceiver->sender()->streams()) {
+ if (!local_streams.Contains(stream))
+ local_streams.push_back(stream);
+ }
}
}
return local_streams;
@@ -1253,37 +1318,46 @@ MediaStreamVector RTCPeerConnection::getLocalStreams() const {
MediaStreamVector RTCPeerConnection::getRemoteStreams() const {
MediaStreamVector remote_streams;
- for (const auto& rtp_receiver : rtp_receivers_) {
- for (const auto& stream : rtp_receiver->streams()) {
- if (!remote_streams.Contains(stream))
- remote_streams.push_back(stream);
+ if (sdp_semantics_ == WebRTCSdpSemantics::kPlanB) {
+ for (const auto& receiver : rtp_receivers_) {
+ for (const auto& stream : receiver->streams()) {
+ if (!remote_streams.Contains(stream))
+ remote_streams.push_back(stream);
+ }
+ }
+ } else {
+ for (const auto& transceiver : transceivers_) {
+ if (!transceiver->DirectionHasRecv())
+ continue;
+ for (const auto& stream : transceiver->receiver()->streams()) {
+ if (!remote_streams.Contains(stream))
+ remote_streams.push_back(stream);
+ }
}
}
return remote_streams;
}
-MediaStream* RTCPeerConnection::getRemoteStream(
- MediaStreamDescriptor* descriptor) const {
+MediaStream* RTCPeerConnection::getRemoteStreamById(const WebString& id) const {
for (const auto& rtp_receiver : rtp_receivers_) {
for (const auto& stream : rtp_receiver->streams()) {
- if (stream->Descriptor() == descriptor)
+ if (static_cast<WebString>(stream->id()) == id) {
return stream;
+ }
}
}
return nullptr;
}
-size_t RTCPeerConnection::getRemoteStreamUsageCount(
- MediaStreamDescriptor* descriptor) const {
- size_t usage_count = 0;
+bool RTCPeerConnection::IsRemoteStream(MediaStream* stream) const {
for (const auto& receiver : rtp_receivers_) {
- WebVector<WebMediaStream> streams = receiver->web_receiver().Streams();
- for (const WebMediaStream& stream : streams) {
- if (stream == descriptor)
- ++usage_count;
+ for (const auto& receiver_stream : receiver->streams()) {
+ if (receiver_stream == stream) {
+ return true;
+ }
}
}
- return usage_count;
+ return false;
}
ScriptPromise RTCPeerConnection::getStats(
@@ -1319,7 +1393,7 @@ ScriptPromise RTCPeerConnection::getStats(
exception_state.ThrowTypeError(
"The argument provided as parameter 1 is neither a callback (function) "
"or selector (MediaStreamTrack or null).");
- return exception_state.Reject(script_state);
+ return ScriptPromise::Reject(script_state, exception_state);
}
ScriptPromise RTCPeerConnection::getStats(ScriptState* script_state,
@@ -1363,7 +1437,7 @@ ScriptPromise RTCPeerConnection::PromiseBasedGetStats(
LOG(ERROR) << "Internal error: peer_handler_ has been discarded";
return ScriptPromise::RejectWithDOMException(
script_state,
- DOMException::Create(kOperationError,
+ DOMException::Create(DOMExceptionCode::kOperationError,
"Internal error: release in progress"));
}
ScriptPromiseResolver* resolver =
@@ -1394,14 +1468,14 @@ ScriptPromise RTCPeerConnection::PromiseBasedGetStats(
if (track_uses == 0u) {
return ScriptPromise::RejectWithDOMException(
script_state,
- DOMException::Create(kInvalidAccessError,
+ DOMException::Create(DOMExceptionCode::kInvalidAccessError,
"There is no sender or receiver for the track."));
}
if (track_uses > 1u) {
return ScriptPromise::RejectWithDOMException(
script_state,
DOMException::Create(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
"There are more than one sender or receiver for the track."));
}
// There is just one use of the track, a sender or receiver.
@@ -1413,6 +1487,11 @@ ScriptPromise RTCPeerConnection::PromiseBasedGetStats(
return track_receiver->getStats(script_state);
}
+const HeapVector<Member<RTCRtpTransceiver>>&
+RTCPeerConnection::getTransceivers() const {
+ return transceivers_;
+}
+
const HeapVector<Member<RTCRtpSender>>& RTCPeerConnection::getSenders() const {
return rtp_senders_;
}
@@ -1422,6 +1501,50 @@ const HeapVector<Member<RTCRtpReceiver>>& RTCPeerConnection::getReceivers()
return rtp_receivers_;
}
+RTCRtpTransceiver* RTCPeerConnection::addTransceiver(
+ const MediaStreamTrackOrString& track_or_kind,
+ const RTCRtpTransceiverInit& init,
+ ExceptionState& exception_state) {
+ if (sdp_semantics_ != WebRTCSdpSemantics::kUnifiedPlan) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ kOnlySupportedInUnifiedPlanMessage);
+ return nullptr;
+ }
+ if (ThrowExceptionIfSignalingStateClosed(signaling_state_, exception_state))
+ return nullptr;
+ auto webrtc_init = ToRtpTransceiverInit(init);
+ webrtc::RTCErrorOr<std::unique_ptr<WebRTCRtpTransceiver>> result =
+ webrtc::RTCError(webrtc::RTCErrorType::UNSUPPORTED_OPERATION);
+ if (track_or_kind.IsMediaStreamTrack()) {
+ MediaStreamTrack* track = track_or_kind.GetAsMediaStreamTrack();
+ RegisterTrack(track);
+ result = peer_handler_->AddTransceiverWithTrack(track->Component(),
+ std::move(webrtc_init));
+ } else {
+ const String& kind_string = track_or_kind.GetAsString();
+ // TODO(hbos): Make cricket::MediaType an allowed identifier in
+ // rtc_peer_connection.cc and use that instead of a boolean.
+ std::string kind;
+ if (kind_string == "audio") {
+ kind = webrtc::MediaStreamTrackInterface::kAudioKind;
+ } else if (kind_string == "video") {
+ kind = webrtc::MediaStreamTrackInterface::kVideoKind;
+ } else {
+ exception_state.ThrowTypeError(
+ "The argument provided as parameter 1 is not a valid "
+ "MediaStreamTrack kind ('audio' or 'video').");
+ return nullptr;
+ }
+ result = peer_handler_->AddTransceiverWithKind(std::move(kind),
+ std::move(webrtc_init));
+ }
+ if (!result.ok()) {
+ ThrowExceptionFromRTCError(result.error(), exception_state);
+ return nullptr;
+ }
+ return CreateOrUpdateTransceiver(result.MoveValue());
+}
+
RTCRtpSender* RTCPeerConnection::addTrack(MediaStreamTrack* track,
MediaStreamVector streams,
ExceptionState& exception_state) {
@@ -1429,22 +1552,19 @@ RTCRtpSender* RTCPeerConnection::addTrack(MediaStreamTrack* track,
DCHECK(track->Component());
if (ThrowExceptionIfSignalingStateClosed(signaling_state_, exception_state))
return nullptr;
- // TODO(bugs.webrtc.org/8530): Take out WebRTCSdpSemantics::kDefault check
- // once default is no longer interpreted as Plan B lower down.
- if ((sdp_semantics_ == WebRTCSdpSemantics::kPlanB ||
- sdp_semantics_ == WebRTCSdpSemantics::kDefault) &&
- streams.size() >= 2) {
+ if (sdp_semantics_ == WebRTCSdpSemantics::kPlanB && streams.size() >= 2) {
// TODO(hbos): Update peer_handler_ to call the AddTrack() that returns the
// appropriate errors, and let the lower layers handle it.
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"Adding a track to multiple streams is not supported.");
return nullptr;
}
for (const auto& sender : rtp_senders_) {
if (sender->track() == track) {
exception_state.ThrowDOMException(
- kInvalidAccessError, "A sender already exists for the track.");
+ DOMExceptionCode::kInvalidAccessError,
+ "A sender already exists for the track.");
return nullptr;
}
}
@@ -1453,20 +1573,46 @@ RTCRtpSender* RTCPeerConnection::addTrack(MediaStreamTrack* track,
for (size_t i = 0; i < streams.size(); ++i) {
web_streams[i] = streams[i]->Descriptor();
}
- std::unique_ptr<WebRTCRtpSender> web_rtp_sender =
- peer_handler_->AddTrack(track->Component(), web_streams);
- if (!web_rtp_sender) {
- exception_state.ThrowDOMException(
- kNotSupportedError, "A sender could not be created for this track.");
+ webrtc::RTCErrorOr<std::unique_ptr<WebRTCRtpTransceiver>>
+ error_or_transceiver =
+ peer_handler_->AddTrack(track->Component(), web_streams);
+ if (!error_or_transceiver.ok()) {
+ ThrowExceptionFromRTCError(error_or_transceiver.error(), exception_state);
return nullptr;
}
- DCHECK(FindSender(*web_rtp_sender) == rtp_senders_.end());
- RTCRtpSender* rtp_sender =
- new RTCRtpSender(this, std::move(web_rtp_sender), track, streams);
- tracks_.insert(track->Component(), track);
- rtp_senders_.push_back(rtp_sender);
- return rtp_sender;
+ auto web_transceiver = error_or_transceiver.MoveValue();
+
+ // The track must be known to the peer connection when performing
+ // CreateOrUpdateSender() below.
+ RegisterTrack(track);
+
+ auto stream_ids = web_transceiver->Sender()->StreamIds();
+ RTCRtpSender* sender;
+ if (sdp_semantics_ == WebRTCSdpSemantics::kPlanB) {
+ DCHECK_EQ(web_transceiver->ImplementationType(),
+ WebRTCRtpTransceiverImplementationType::kPlanBSenderOnly);
+ sender = CreateOrUpdateSender(web_transceiver->Sender(), track->kind());
+ } else {
+ DCHECK_EQ(sdp_semantics_, WebRTCSdpSemantics::kUnifiedPlan);
+ DCHECK_EQ(web_transceiver->ImplementationType(),
+ WebRTCRtpTransceiverImplementationType::kFullTransceiver);
+ RTCRtpTransceiver* transceiver =
+ CreateOrUpdateTransceiver(std::move(web_transceiver));
+ sender = transceiver->sender();
+ }
+ // Newly created senders have no streams set, we have to set it ourselves.
+ sender->set_streams(streams);
+
+ // The stream IDs should match between layers, with one exception;
+ // in Plan B if no stream was supplied, the lower layer still generates a
+ // stream which has no blink layer correspondence.
+ DCHECK(sdp_semantics_ != WebRTCSdpSemantics::kPlanB ||
+ (streams.size() == 0u && stream_ids.size() == 1u) ||
+ stream_ids.size() == streams.size());
+ DCHECK(sdp_semantics_ != WebRTCSdpSemantics::kUnifiedPlan ||
+ stream_ids.size() == streams.size());
+ return sender;
}
void RTCPeerConnection::removeTrack(RTCRtpSender* sender,
@@ -1477,24 +1623,34 @@ void RTCPeerConnection::removeTrack(RTCRtpSender* sender,
auto* it = FindSender(*sender->web_sender());
if (it == rtp_senders_.end()) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
"The sender was not created by this peer connection.");
return;
}
- if (!peer_handler_->RemoveTrack(sender->web_sender())) {
- // Operation aborted. This indicates that the sender is no longer used by
- // the peer connection, i.e. that it was removed due to setting a remote
- // description of type "rollback".
- // Note: Until the WebRTC library supports re-using senders, a sender will
- // also stop being used as a result of being removed.
- return;
+ auto error_or_transceiver = peer_handler_->RemoveTrack(sender->web_sender());
+ if (sdp_semantics_ == WebRTCSdpSemantics::kPlanB) {
+ // Plan B: Was the sender removed?
+ if (!error_or_transceiver.ok()) {
+ // Operation aborted. This indicates that the sender is no longer used by
+ // the peer connection, i.e. that it was removed due to setting a remote
+ // description of type "rollback".
+ return;
+ }
+ // Successfully removing the track results in the sender's track property
+ // being nulled.
+ DCHECK(!sender->web_sender()->Track());
+ sender->SetTrack(nullptr);
+ rtp_senders_.erase(it);
+ } else {
+ // Unified Plan: Was the transceiver updated?
+ DCHECK_EQ(sdp_semantics_, WebRTCSdpSemantics::kUnifiedPlan);
+ if (!error_or_transceiver.ok()) {
+ ThrowExceptionFromRTCError(error_or_transceiver.error(), exception_state);
+ return;
+ }
+ CreateOrUpdateTransceiver(error_or_transceiver.MoveValue());
}
- // Successfully removing the track results in the sender's track property
- // being nulled.
- DCHECK(!sender->web_sender()->Track());
- sender->SetTrack(nullptr);
- rtp_senders_.erase(it);
}
RTCDataChannel* RTCPeerConnection::createDataChannel(
@@ -1508,7 +1664,16 @@ RTCDataChannel* RTCPeerConnection::createDataChannel(
WebRTCDataChannelInit init;
init.ordered = data_channel_dict.ordered();
ExecutionContext* context = ExecutionContext::From(script_state);
- if (data_channel_dict.hasMaxRetransmitTime()) {
+ // maxPacketLifeTime and maxRetransmitTime are two names for the same thing,
+ // but maxPacketLifeTime is the standardized name so it takes precedence.
+ if (data_channel_dict.hasMaxPacketLifeTime()) {
+ UseCounter::Count(
+ context,
+ WebFeature::kRTCPeerConnectionCreateDataChannelMaxPacketLifeTime);
+ init.max_retransmit_time = data_channel_dict.maxPacketLifeTime();
+ } else if (data_channel_dict.hasMaxRetransmitTime()) {
+ Deprecation::CountDeprecation(
+ context, WebFeature::kRTCDataChannelInitMaxRetransmitTime);
UseCounter::Count(
context,
WebFeature::kRTCPeerConnectionCreateDataChannelMaxRetransmitTime);
@@ -1574,13 +1739,111 @@ HeapVector<Member<RTCRtpReceiver>>::iterator RTCPeerConnection::FindReceiver(
return rtp_receivers_.end();
}
+HeapVector<Member<RTCRtpTransceiver>>::iterator
+RTCPeerConnection::FindTransceiver(
+ const WebRTCRtpTransceiver& web_transceiver) {
+ for (auto* it = transceivers_.begin(); it != transceivers_.end(); ++it) {
+ if ((*it)->web_transceiver()->Id() == web_transceiver.Id())
+ return it;
+ }
+ return transceivers_.end();
+}
+
+RTCRtpSender* RTCPeerConnection::CreateOrUpdateSender(
+ std::unique_ptr<WebRTCRtpSender> web_sender,
+ String kind) {
+ // The track corresponding to |web_track| must already be known to us by being
+ // in |tracks_|, as is a prerequisite of CreateOrUpdateSender().
+ WebMediaStreamTrack web_track = web_sender->Track();
+ MediaStreamTrack* track;
+ if (web_track.IsNull()) {
+ track = nullptr;
+ } else {
+ track = tracks_.at(web_track);
+ DCHECK(track);
+ }
+
+ // Create or update sender. If the web sender has stream IDs the sender's
+ // streams need to be set separately outside of this method.
+ auto* sender_it = FindSender(*web_sender);
+ RTCRtpSender* sender;
+ if (sender_it == rtp_senders_.end()) {
+ // Create new sender (with empty stream set).
+ sender = new RTCRtpSender(this, std::move(web_sender), kind, track, {});
+ rtp_senders_.push_back(sender);
+ } else {
+ // Update existing sender (not touching the stream set).
+ sender = *sender_it;
+ DCHECK_EQ(sender->web_sender()->Id(), web_sender->Id());
+ sender->SetTrack(track);
+ }
+ return sender;
+}
+
+RTCRtpReceiver* RTCPeerConnection::CreateOrUpdateReceiver(
+ std::unique_ptr<WebRTCRtpReceiver> web_receiver) {
+ auto* receiver_it = FindReceiver(*web_receiver);
+ // Create track.
+ MediaStreamTrack* track;
+ if (receiver_it == rtp_receivers_.end()) {
+ track =
+ MediaStreamTrack::Create(GetExecutionContext(), web_receiver->Track());
+ RegisterTrack(track);
+ } else {
+ track = (*receiver_it)->track();
+ }
+
+ // Create or update receiver. If the web receiver has stream IDs the
+ // receiver's streams need to be set separately outside of this method.
+ RTCRtpReceiver* receiver;
+ if (receiver_it == rtp_receivers_.end()) {
+ // Create new receiver.
+ receiver = new RTCRtpReceiver(std::move(web_receiver), track, {});
+ rtp_receivers_.push_back(receiver);
+ } else {
+ // Update existing receiver is a no-op.
+ receiver = *receiver_it;
+ DCHECK_EQ(receiver->web_receiver().Id(), web_receiver->Id());
+ DCHECK_EQ(receiver->track(), track); // Its track should never change.
+ }
+ return receiver;
+}
+
+RTCRtpTransceiver* RTCPeerConnection::CreateOrUpdateTransceiver(
+ std::unique_ptr<WebRTCRtpTransceiver> web_transceiver) {
+ String kind = (web_transceiver->Receiver()->Track().Source().GetType() ==
+ WebMediaStreamSource::kTypeAudio)
+ ? "audio"
+ : "video";
+ RTCRtpSender* sender = CreateOrUpdateSender(web_transceiver->Sender(), kind);
+ RTCRtpReceiver* receiver =
+ CreateOrUpdateReceiver(web_transceiver->Receiver());
+
+ RTCRtpTransceiver* transceiver;
+ auto* transceiver_it = FindTransceiver(*web_transceiver);
+ if (transceiver_it == transceivers_.end()) {
+ // Create new tranceiver.
+ transceiver = new RTCRtpTransceiver(this, std::move(web_transceiver),
+ sender, receiver);
+ transceivers_.push_back(transceiver);
+ } else {
+ // Update existing transceiver.
+ transceiver = *transceiver_it;
+ // The sender and receiver have already been updated above.
+ DCHECK_EQ(transceiver->sender(), sender);
+ DCHECK_EQ(transceiver->receiver(), receiver);
+ transceiver->UpdateMembers();
+ }
+ return transceiver;
+}
+
RTCDTMFSender* RTCPeerConnection::createDTMFSender(
MediaStreamTrack* track,
ExceptionState& exception_state) {
if (ThrowExceptionIfSignalingStateClosed(signaling_state_, exception_state))
return nullptr;
if (track->kind() != "audio") {
- exception_state.ThrowDOMException(kSyntaxError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
"track.kind is not 'audio'.");
return nullptr;
}
@@ -1593,26 +1856,32 @@ RTCDTMFSender* RTCPeerConnection::createDTMFSender(
}
if (!found_rtp_sender) {
exception_state.ThrowDOMException(
- kSyntaxError, "No RTCRtpSender is available for the track provided.");
+ DOMExceptionCode::kSyntaxError,
+ "No RTCRtpSender is available for the track provided.");
return nullptr;
}
RTCDTMFSender* dtmf_sender = found_rtp_sender->dtmf();
if (!dtmf_sender) {
- exception_state.ThrowDOMException(kSyntaxError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
"Unable to create DTMF sender for track");
return nullptr;
}
- dtmf_sender->SetTrack(track);
return dtmf_sender;
}
void RTCPeerConnection::close() {
- if (signaling_state_ == RTCPeerConnection::kSignalingStateClosed)
+ if (signaling_state_ ==
+ webrtc::PeerConnectionInterface::SignalingState::kClosed)
return;
CloseInternal();
}
+void RTCPeerConnection::RegisterTrack(MediaStreamTrack* track) {
+ DCHECK(track);
+ tracks_.insert(track->Component(), track);
+}
+
void RTCPeerConnection::NoteSdpCreated(const RTCSessionDescription& desc) {
if (desc.type() == "offer") {
last_offer_ = desc.sdp();
@@ -1674,10 +1943,11 @@ void RTCPeerConnection::DidGenerateICECandidate(
ScheduleDispatchEvent(RTCPeerConnectionIceEvent::Create(ice_candidate));
}
-void RTCPeerConnection::DidChangeSignalingState(SignalingState new_state) {
+void RTCPeerConnection::DidChangeSignalingState(
+ webrtc::PeerConnectionInterface::SignalingState new_state) {
DCHECK(!closed_);
DCHECK(GetExecutionContext()->IsContextThread());
- ChangeSignalingState(new_state);
+ ChangeSignalingState(new_state, true);
}
void RTCPeerConnection::DidChangeICEGatheringState(
@@ -1694,118 +1964,84 @@ void RTCPeerConnection::DidChangeICEConnectionState(
ChangeIceConnectionState(new_state);
}
-void RTCPeerConnection::DidAddRemoteTrack(
- std::unique_ptr<WebRTCRtpReceiver> web_rtp_receiver) {
+void RTCPeerConnection::DidAddReceiverPlanB(
+ std::unique_ptr<WebRTCRtpReceiver> web_receiver) {
DCHECK(!closed_);
DCHECK(GetExecutionContext()->IsContextThread());
- if (signaling_state_ == kSignalingStateClosed)
+ DCHECK_EQ(sdp_semantics_, WebRTCSdpSemantics::kPlanB);
+ if (signaling_state_ ==
+ webrtc::PeerConnectionInterface::SignalingState::kClosed)
return;
+ // Create track.
+ MediaStreamTrack* track =
+ MediaStreamTrack::Create(GetExecutionContext(), web_receiver->Track());
+ tracks_.insert(track->Component(), track);
+ // Create or update streams.
HeapVector<Member<MediaStream>> streams;
- WebVector<WebMediaStream> web_streams = web_rtp_receiver->Streams();
- streams.ReserveCapacity(web_streams.size());
- for (const WebMediaStream& web_stream : web_streams) {
- MediaStream* stream = getRemoteStream(web_stream);
+ for (const auto& stream_id : web_receiver->StreamIds()) {
+ MediaStream* stream = getRemoteStreamById(stream_id);
if (!stream) {
- // This is a new stream that we need to create.
- // Get or create audio tracks.
- WebVector<WebMediaStreamTrack> audio_web_tracks;
- web_stream.AudioTracks(audio_web_tracks);
+ // The stream is new, create it containing this track.
+ MediaStreamComponentVector audio_track_components;
MediaStreamTrackVector audio_tracks;
- audio_tracks.ReserveCapacity(audio_web_tracks.size());
- for (const WebMediaStreamTrack& audio_web_track : audio_web_tracks) {
- MediaStreamTrack* audio_track = tracks_.at(audio_web_track);
- if (!audio_track) {
- audio_track =
- MediaStreamTrack::Create(GetExecutionContext(), audio_web_track);
- tracks_.insert(audio_track->Component(), audio_track);
- }
- audio_tracks.push_back(audio_track);
- }
- // Get or create video tracks.
- WebVector<WebMediaStreamTrack> video_web_tracks;
- web_stream.VideoTracks(video_web_tracks);
+ MediaStreamComponentVector video_track_components;
MediaStreamTrackVector video_tracks;
- video_tracks.ReserveCapacity(video_web_tracks.size());
- for (const WebMediaStreamTrack& video_web_track : video_web_tracks) {
- MediaStreamTrack* video_track = tracks_.at(video_web_track);
- if (!video_track) {
- video_track =
- MediaStreamTrack::Create(GetExecutionContext(), video_web_track);
- tracks_.insert(video_track->Component(), video_track);
- }
- video_tracks.push_back(video_track);
+ if (track->Component()->Source()->GetType() ==
+ MediaStreamSource::kTypeAudio) {
+ audio_track_components.push_back(track->Component());
+ audio_tracks.push_back(track);
+ } else {
+ DCHECK(track->Component()->Source()->GetType() ==
+ MediaStreamSource::kTypeVideo);
+ video_track_components.push_back(track->Component());
+ video_tracks.push_back(track);
}
- // Create stream with tracks.
- stream = MediaStream::Create(GetExecutionContext(), web_stream,
- audio_tracks, video_tracks);
- stream->RegisterObserver(this);
+ MediaStreamDescriptor* descriptor = MediaStreamDescriptor::Create(
+ stream_id, std::move(audio_track_components),
+ std::move(video_track_components));
+ stream =
+ MediaStream::Create(GetExecutionContext(), descriptor,
+ std::move(audio_tracks), std::move(video_tracks));
+ // Schedule to fire "pc.onaddstream".
ScheduleDispatchEvent(
MediaStreamEvent::Create(EventTypeNames::addstream, stream));
} else {
- // The stream already exists. Because the blink stream is wired up to
- // reflect when web tracks are added to the corresponding web stream, the
- // receiver's track will already have a blink track created for it and
- // added to the blink stream. Find it and add it to |tracks_| so that the
- // RTCPeerConnection knows of its existence.
- // TODO(hbos): This wiring is problematic since it assumes the blink track
- // should always be created. If the track already exists (on some other
- // stream or receiver) we will end up with multiple blink tracks for the
- // same component. When a web track is added to the web stream, we need to
- // check if a blink track already exists for it by querying the
- // RTCPeerConnection. https://crbug.com/769743
- MediaStreamTrack* receiver_track = nullptr;
- for (const auto& track : stream->getTracks()) {
- if (track->Component() == web_rtp_receiver->Track()) {
- receiver_track = track;
- break;
- }
- }
- DCHECK(receiver_track);
- tracks_.insert(receiver_track->Component(), receiver_track);
+ // The stream already exists, add the track to it.
+ // This will cause to schedule to fire "stream.onaddtrack".
+ stream->AddTrackAndFireEvents(track);
}
streams.push_back(stream);
}
- DCHECK(FindReceiver(*web_rtp_receiver) == rtp_receivers_.end());
- MediaStreamTrack* track = GetTrack(web_rtp_receiver->Track());
- if (!track) {
- // Receiver with track, without a stream. May be created by Unified Plan.
- track = MediaStreamTrack::Create(GetExecutionContext(),
- web_rtp_receiver->Track());
- }
+ DCHECK(FindReceiver(*web_receiver) == rtp_receivers_.end());
RTCRtpReceiver* rtp_receiver =
- new RTCRtpReceiver(std::move(web_rtp_receiver), track, streams);
+ new RTCRtpReceiver(std::move(web_receiver), track, streams);
rtp_receivers_.push_back(rtp_receiver);
ScheduleDispatchEvent(
- new RTCTrackEvent(rtp_receiver, rtp_receiver->track(), streams));
+ new RTCTrackEvent(rtp_receiver, rtp_receiver->track(), streams, nullptr));
}
-void RTCPeerConnection::DidRemoveRemoteTrack(
- std::unique_ptr<WebRTCRtpReceiver> web_rtp_receiver) {
+void RTCPeerConnection::DidRemoveReceiverPlanB(
+ std::unique_ptr<WebRTCRtpReceiver> web_receiver) {
DCHECK(!closed_);
DCHECK(GetExecutionContext()->IsContextThread());
+ DCHECK_EQ(sdp_semantics_, WebRTCSdpSemantics::kPlanB);
- WebVector<WebMediaStream> web_streams = web_rtp_receiver->Streams();
- auto* it = FindReceiver(*web_rtp_receiver);
+ auto* it = FindReceiver(*web_receiver);
DCHECK(it != rtp_receivers_.end());
RTCRtpReceiver* rtp_receiver = *it;
+ auto streams = rtp_receiver->streams();
MediaStreamTrack* track = rtp_receiver->track();
rtp_receivers_.erase(it);
// End streams no longer in use and fire "removestream" events. This behavior
// is no longer in the spec.
- for (const WebMediaStream& web_stream : web_streams) {
- MediaStreamDescriptor* stream_descriptor = web_stream;
- DCHECK(stream_descriptor->Client());
- MediaStream* stream =
- static_cast<MediaStream*>(stream_descriptor->Client());
-
- // The track should already have been removed from the stream thanks to
- // wiring listening to the webrtc layer stream. This should make sure the
- // "removetrack" event fires.
- DCHECK(!stream->getTracks().Contains(track));
+ for (const auto& stream : streams) {
+ // Remove the track.
+ // This will cause to schedule to fire "stream.onremovetrack".
+ stream->RemoveTrackAndFireEvents(track);
// Was this the last usage of the stream? Remove from remote streams.
- if (!getRemoteStreamUsageCount(web_stream)) {
+ if (!IsRemoteStream(stream)) {
// TODO(hbos): The stream should already have ended by being empty, no
// need for |StreamEnded|.
stream->StreamEnded();
@@ -1820,12 +2056,132 @@ void RTCPeerConnection::DidRemoveRemoteTrack(
MediaStreamSource::kReadyStateMuted);
}
+void RTCPeerConnection::DidModifyTransceivers(
+ std::vector<std::unique_ptr<WebRTCRtpTransceiver>> web_transceivers,
+ bool is_remote_description) {
+ HeapVector<Member<MediaStreamTrack>> mute_tracks;
+ HeapVector<std::pair<Member<MediaStream>, Member<MediaStreamTrack>>>
+ remove_list;
+ HeapVector<std::pair<Member<MediaStream>, Member<MediaStreamTrack>>> add_list;
+ HeapVector<Member<RTCRtpTransceiver>> track_events;
+ for (auto& web_transceiver : web_transceivers) {
+ auto* it = FindTransceiver(*web_transceiver);
+ bool previously_had_recv =
+ (it != transceivers_.end()) ? (*it)->FiredDirectionHasRecv() : false;
+ RTCRtpTransceiver* transceiver =
+ CreateOrUpdateTransceiver(std::move(web_transceiver));
+
+ // The transceiver is now up-to-date. Compare before/after values of
+ // FiredDirectionHasRecv() and process the remote track if it changed.
+ if (is_remote_description && !previously_had_recv &&
+ transceiver->FiredDirectionHasRecv()) {
+ ProcessAdditionOfRemoteTrack(
+ transceiver, transceiver->web_transceiver()->Receiver()->StreamIds(),
+ &add_list, &track_events);
+ }
+ if (previously_had_recv && !transceiver->FiredDirectionHasRecv()) {
+ ProcessRemovalOfRemoteTrack(transceiver, &remove_list, &mute_tracks);
+ }
+ }
+
+ for (auto& track : mute_tracks) {
+ track->Component()->Source()->SetReadyState(
+ MediaStreamSource::kReadyStateMuted);
+ }
+ for (auto& pair : remove_list) {
+ auto& stream = pair.first;
+ auto& track = pair.second;
+ if (stream->getTracks().Contains(track)) {
+ stream->RemoveTrackAndFireEvents(track);
+ }
+ }
+ for (auto& pair : add_list) {
+ auto& stream = pair.first;
+ auto& track = pair.second;
+ if (!stream->getTracks().Contains(track)) {
+ stream->AddTrackAndFireEvents(track);
+ }
+ }
+
+ for (auto& transceiver : track_events) {
+ ScheduleDispatchEvent(new RTCTrackEvent(
+ transceiver->receiver(), transceiver->receiver()->track(),
+ transceiver->receiver()->streams(), transceiver));
+ }
+}
+
+void RTCPeerConnection::ProcessAdditionOfRemoteTrack(
+ RTCRtpTransceiver* transceiver,
+ const WebVector<WebString>& stream_ids,
+ HeapVector<std::pair<Member<MediaStream>, Member<MediaStreamTrack>>>*
+ add_list,
+ HeapVector<Member<RTCRtpTransceiver>>* track_events) {
+ SetAssociatedMediaStreams(transceiver->receiver(), stream_ids, nullptr,
+ add_list);
+ track_events->push_back(transceiver);
+}
+
+void RTCPeerConnection::ProcessRemovalOfRemoteTrack(
+ RTCRtpTransceiver* transceiver,
+ HeapVector<std::pair<Member<MediaStream>, Member<MediaStreamTrack>>>*
+ remove_list,
+ HeapVector<Member<MediaStreamTrack>>* mute_tracks) {
+ WebVector<WebString> stream_ids = {};
+ SetAssociatedMediaStreams(transceiver->receiver(), stream_ids, remove_list,
+ nullptr);
+ if (!transceiver->receiver()->track()->muted())
+ mute_tracks->push_back(transceiver->receiver()->track());
+}
+
+void RTCPeerConnection::SetAssociatedMediaStreams(
+ RTCRtpReceiver* receiver,
+ const WebVector<WebString>& stream_ids,
+ HeapVector<std::pair<Member<MediaStream>, Member<MediaStreamTrack>>>*
+ remove_list,
+ HeapVector<std::pair<Member<MediaStream>, Member<MediaStreamTrack>>>*
+ add_list) {
+ MediaStreamVector known_streams = getRemoteStreams();
+
+ MediaStreamVector streams;
+ for (const auto& stream_id : stream_ids) {
+ MediaStream* curr_stream = nullptr;
+ for (const auto& known_stream : known_streams) {
+ if (static_cast<WebString>(known_stream->id()) == stream_id) {
+ curr_stream = known_stream;
+ break;
+ }
+ }
+ if (!curr_stream) {
+ curr_stream = MediaStream::Create(
+ GetExecutionContext(), MediaStreamDescriptor::Create(
+ static_cast<String>(stream_id), {}, {}));
+ }
+ streams.push_back(curr_stream);
+ }
+
+ const MediaStreamVector& prev_streams = receiver->streams();
+ if (remove_list) {
+ for (const auto& stream : prev_streams) {
+ if (!streams.Contains(stream))
+ remove_list->push_back(std::make_pair(stream, receiver->track()));
+ }
+ }
+ if (add_list) {
+ for (const auto& stream : streams) {
+ if (!prev_streams.Contains(stream))
+ add_list->push_back(std::make_pair(stream, receiver->track()));
+ }
+ }
+ receiver->set_streams(std::move(streams));
+}
+
void RTCPeerConnection::DidAddRemoteDataChannel(
WebRTCDataChannelHandler* handler) {
DCHECK(!closed_);
DCHECK(GetExecutionContext()->IsContextThread());
- if (signaling_state_ == kSignalingStateClosed)
+ if (signaling_state_ ==
+ webrtc::PeerConnectionInterface::SignalingState::kClosed)
return;
RTCDataChannel* channel =
@@ -1841,7 +2197,7 @@ void RTCPeerConnection::ReleasePeerConnectionHandler() {
stopped_ = true;
ice_connection_state_ = kICEConnectionStateClosed;
- signaling_state_ = kSignalingStateClosed;
+ signaling_state_ = webrtc::PeerConnectionInterface::SignalingState::kClosed;
dispatch_scheduled_event_runner_->Stop();
@@ -1851,17 +2207,11 @@ void RTCPeerConnection::ReleasePeerConnectionHandler() {
}
void RTCPeerConnection::ClosePeerConnection() {
- DCHECK(signaling_state_ != RTCPeerConnection::kSignalingStateClosed);
+ DCHECK(signaling_state_ !=
+ webrtc::PeerConnectionInterface::SignalingState::kClosed);
CloseInternal();
}
-RTCPeerConnection::WebRTCOriginTrials RTCPeerConnection::GetOriginTrials() {
- RTCPeerConnection::WebRTCOriginTrials trials;
- trials.vaapi_hwvp8_encoding_enabled =
- OriginTrials::webRtcVaapiHWVP8EncodingEnabled(GetExecutionContext());
- return trials;
-}
-
const AtomicString& RTCPeerConnection::InterfaceName() const {
return EventTargetNames::RTCPeerConnection;
}
@@ -1882,10 +2232,19 @@ void RTCPeerConnection::ContextDestroyed(ExecutionContext*) {
ReleasePeerConnectionHandler();
}
-void RTCPeerConnection::ChangeSignalingState(SignalingState signaling_state) {
- if (signaling_state_ != kSignalingStateClosed) {
+void RTCPeerConnection::ChangeSignalingState(
+ webrtc::PeerConnectionInterface::SignalingState signaling_state,
+ bool dispatch_event_immediately) {
+ if (signaling_state_ == signaling_state)
+ return;
+ if (signaling_state_ !=
+ webrtc::PeerConnectionInterface::SignalingState::kClosed) {
signaling_state_ = signaling_state;
- ScheduleDispatchEvent(Event::Create(EventTypeNames::signalingstatechange));
+ Event* event = Event::Create(EventTypeNames::signalingstatechange);
+ if (dispatch_event_immediately)
+ DispatchEvent(event);
+ else
+ ScheduleDispatchEvent(event);
}
}
@@ -1938,12 +2297,18 @@ bool RTCPeerConnection::SetIceConnectionState(
}
void RTCPeerConnection::CloseInternal() {
- DCHECK(signaling_state_ != RTCPeerConnection::kSignalingStateClosed);
+ DCHECK(signaling_state_ !=
+ webrtc::PeerConnectionInterface::SignalingState::kClosed);
peer_handler_->Stop();
closed_ = true;
ChangeIceConnectionState(kICEConnectionStateClosed);
- ChangeSignalingState(kSignalingStateClosed);
+ ChangeSignalingState(webrtc::PeerConnectionInterface::SignalingState::kClosed,
+ false);
+ for (auto& transceiver : transceivers_) {
+ transceiver->OnPeerConnectionClosed();
+ }
+
Document* document = ToDocument(GetExecutionContext());
HostsUsingFeatures::CountAnyWorld(
*document, HostsUsingFeatures::Feature::kRTCPeerConnectionUsed);
@@ -2006,6 +2371,7 @@ void RTCPeerConnection::Trace(blink::Visitor* visitor) {
visitor->Trace(tracks_);
visitor->Trace(rtp_senders_);
visitor->Trace(rtp_receivers_);
+ visitor->Trace(transceivers_);
visitor->Trace(dispatch_scheduled_event_runner_);
visitor->Trace(scheduled_events_);
EventTargetWithInlineData::Trace(visitor);