summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
diff options
context:
space:
mode:
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.cc122
1 files changed, 85 insertions, 37 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 2ec6259205e..1503444ac29 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
@@ -184,7 +184,7 @@ bool IsIceCandidateMissingSdp(
const RTCIceCandidateInit* ice_candidate_init =
candidate.GetAsRTCIceCandidateInit();
return ice_candidate_init->sdpMid().IsNull() &&
- !ice_candidate_init->hasSdpMLineIndex();
+ !ice_candidate_init->hasSdpMLineIndexNonNull();
}
DCHECK(candidate.IsRTCIceCandidate());
@@ -221,8 +221,8 @@ RTCIceCandidatePlatform* ConvertToRTCIceCandidatePlatform(
candidate.GetAsRTCIceCandidateInit();
// TODO(guidou): Change default value to -1. crbug.com/614958.
uint16_t sdp_m_line_index = 0;
- if (ice_candidate_init->hasSdpMLineIndex()) {
- sdp_m_line_index = ice_candidate_init->sdpMLineIndex();
+ if (ice_candidate_init->hasSdpMLineIndexNonNull()) {
+ sdp_m_line_index = ice_candidate_init->sdpMLineIndexNonNull();
} else {
UseCounter::Count(context,
WebFeature::kRTCIceCandidateDefaultSdpMLineIndex);
@@ -370,9 +370,6 @@ webrtc::PeerConnectionInterface::RTCConfiguration ParseConfiguration(
return {};
}
- String username = ice_server->username();
- String credential = ice_server->credential();
-
for (const String& url_string : url_strings) {
KURL url(NullURL(), url_string);
if (!url.IsValid()) {
@@ -391,7 +388,7 @@ webrtc::PeerConnectionInterface::RTCConfiguration ParseConfiguration(
return {};
}
if ((url.ProtocolIs("turn") || url.ProtocolIs("turns")) &&
- (username.IsNull() || credential.IsNull())) {
+ (!ice_server->hasUsername() || !ice_server->hasCredential())) {
exception_state->ThrowDOMException(
DOMExceptionCode::kInvalidAccessError,
"Both username and credential are "
@@ -402,8 +399,12 @@ webrtc::PeerConnectionInterface::RTCConfiguration ParseConfiguration(
auto converted_ice_server =
webrtc::PeerConnectionInterface::IceServer();
converted_ice_server.urls.push_back(String(url).Utf8());
- converted_ice_server.username = username.Utf8();
- converted_ice_server.password = credential.Utf8();
+ if (ice_server->hasUsername()) {
+ converted_ice_server.username = ice_server->username().Utf8();
+ }
+ if (ice_server->hasCredential()) {
+ converted_ice_server.password = ice_server->credential().Utf8();
+ }
ice_servers.emplace_back(std::move(converted_ice_server));
}
@@ -632,7 +633,7 @@ bool RTCPeerConnection::EventWrapper::Setup() {
return true;
}
-void RTCPeerConnection::EventWrapper::Trace(Visitor* visitor) {
+void RTCPeerConnection::EventWrapper::Trace(Visitor* visitor) const {
visitor->Trace(event_);
}
@@ -749,8 +750,9 @@ RTCPeerConnection::RTCPeerConnection(
peer_connection_state_(
webrtc::PeerConnectionInterface::PeerConnectionState::kNew),
negotiation_needed_(false),
- stopped_(false),
- closed_(false),
+ peer_handler_unregistered_(true),
+ closed_(true),
+ suppress_events_(true),
has_data_channels_(false),
sdp_semantics_(configuration.sdp_semantics),
sdp_semantics_specified_(sdp_semantics_specified),
@@ -769,8 +771,6 @@ RTCPeerConnection::RTCPeerConnection(
// assert in the destructor.
if (InstanceCounters::CounterValue(
InstanceCounters::kRTCPeerConnectionCounter) > kMaxPeerConnections) {
- closed_ = true;
- stopped_ = true;
exception_state.ThrowDOMException(DOMExceptionCode::kUnknownError,
"Cannot create so many PeerConnections");
return;
@@ -790,8 +790,6 @@ RTCPeerConnection::RTCPeerConnection(
}
if (!peer_handler_) {
- closed_ = true;
- stopped_ = true;
exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"No PeerConnection handler can be "
"created, perhaps WebRTC is disabled?");
@@ -801,26 +799,33 @@ RTCPeerConnection::RTCPeerConnection(
auto* web_frame =
static_cast<WebLocalFrame*>(WebFrame::FromFrame(window->GetFrame()));
if (!peer_handler_->Initialize(configuration, constraints, web_frame)) {
- closed_ = true;
- stopped_ = true;
exception_state.ThrowDOMException(
DOMExceptionCode::kNotSupportedError,
"Failed to initialize native PeerConnection.");
return;
}
+ // The RTCPeerConnection was successfully constructed.
+ closed_ = false;
+ peer_handler_unregistered_ = false;
+ suppress_events_ = false;
feature_handle_for_scheduler_ =
window->GetFrame()->GetFrameScheduler()->RegisterFeature(
SchedulingPolicy::Feature::kWebRTC,
- {SchedulingPolicy::DisableAggressiveThrottling(),
- SchedulingPolicy::RecordMetricsForBackForwardCache()});
+ base::FeatureList::IsEnabled(features::kOptOutWebRTCFromAllThrottling)
+ ? SchedulingPolicy{SchedulingPolicy::DisableAllThrottling(),
+ SchedulingPolicy::
+ RecordMetricsForBackForwardCache()}
+ : SchedulingPolicy{
+ SchedulingPolicy::DisableAggressiveThrottling(),
+ SchedulingPolicy::RecordMetricsForBackForwardCache()});
}
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.
- DCHECK(closed_ || stopped_);
+ DCHECK(closed_ || peer_handler_unregistered_);
InstanceCounters::DecrementCounter(
InstanceCounters::kRTCPeerConnectionCounter);
DCHECK_GE(InstanceCounters::CounterValue(
@@ -2302,7 +2307,7 @@ RTCRtpTransceiver* RTCPeerConnection::addTransceiver(
}
if (ThrowExceptionIfSignalingStateClosed(signaling_state_, &exception_state))
return nullptr;
- auto webrtc_init = ToRtpTransceiverInit(init);
+ auto webrtc_init = ToRtpTransceiverInit(GetExecutionContext(), init);
// Validate sendEncodings.
for (auto& encoding : webrtc_init.send_encodings) {
if (encoding.rid.length() > 16) {
@@ -2672,10 +2677,11 @@ RTCRtpReceiver* RTCPeerConnection::CreateOrUpdateReceiver(
RTCRtpTransceiver* RTCPeerConnection::CreateOrUpdateTransceiver(
std::unique_ptr<RTCRtpTransceiverPlatform> platform_transceiver) {
- String kind = (platform_transceiver->Receiver()->Track().Source().GetType() ==
- WebMediaStreamSource::kTypeAudio)
- ? "audio"
- : "video";
+ String kind =
+ (platform_transceiver->Receiver()->Track()->Source()->GetType() ==
+ MediaStreamSource::kTypeAudio)
+ ? "audio"
+ : "video";
RTCRtpSender* sender =
CreateOrUpdateSender(platform_transceiver->Sender(), kind);
RTCRtpReceiver* receiver =
@@ -2770,6 +2776,7 @@ RTCDTMFSender* RTCPeerConnection::createDTMFSender(
}
void RTCPeerConnection::close() {
+ suppress_events_ = true;
if (signaling_state_ ==
webrtc::PeerConnectionInterface::SignalingState::kClosed) {
return;
@@ -2836,7 +2843,7 @@ void RTCPeerConnection::MaybeFireNegotiationNeeded() {
if (!negotiation_needed_ || closed_)
return;
negotiation_needed_ = false;
- DispatchEvent(*Event::Create(event_type_names::kNegotiationneeded));
+ MaybeDispatchEvent(Event::Create(event_type_names::kNegotiationneeded));
}
void RTCPeerConnection::DidGenerateICECandidate(
@@ -3123,7 +3130,7 @@ void RTCPeerConnection::DidModifyTransceivers(
auto* track_event = MakeGarbageCollected<RTCTrackEvent>(
transceiver->receiver(), transceiver->receiver()->track(),
transceiver->receiver()->streams(), transceiver);
- DispatchEvent(*track_event);
+ MaybeDispatchEvent(track_event);
}
// Unmute "pc.ontrack" tracks. Fires "track.onunmute" synchronously.
@@ -3201,7 +3208,7 @@ void RTCPeerConnection::DidAddRemoteDataChannel(
GetExecutionContext(), std::move(channel), peer_handler_.get());
has_data_channels_ = true;
blink_channel->SetStateToOpenWithoutEvent();
- DispatchEvent(*MakeGarbageCollected<RTCDataChannelEvent>(
+ MaybeDispatchEvent(MakeGarbageCollected<RTCDataChannelEvent>(
event_type_names::kDatachannel, blink_channel));
// The event handler might have closed the channel.
if (blink_channel->readyState() == "open") {
@@ -3213,22 +3220,27 @@ void RTCPeerConnection::DidNoteInterestingUsage(int usage_pattern) {
if (!GetExecutionContext())
return;
LocalDOMWindow* window = To<LocalDOMWindow>(GetExecutionContext());
- ukm::SourceId source_id = window->document()->UkmSourceID();
+ ukm::SourceId source_id = window->UkmSourceID();
ukm::builders::WebRTC_AddressHarvesting(source_id)
.SetUsagePattern(usage_pattern)
- .Record(window->document()->UkmRecorder());
+ .Record(window->UkmRecorder());
}
void RTCPeerConnection::UnregisterPeerConnectionHandler() {
- if (stopped_)
+ if (peer_handler_unregistered_) {
+ DCHECK(scheduled_events_.IsEmpty())
+ << "Undelivered events can cause memory leaks due to "
+ << "WrapPersistent(this) in setup function callbacks";
return;
+ }
- stopped_ = true;
+ peer_handler_unregistered_ = true;
ice_connection_state_ = webrtc::PeerConnectionInterface::kIceConnectionClosed;
signaling_state_ = webrtc::PeerConnectionInterface::SignalingState::kClosed;
peer_handler_->StopAndUnregister();
dispatch_scheduled_events_task_handle_.Cancel();
+ scheduled_events_.clear();
feature_handle_for_scheduler_.reset();
}
@@ -3247,6 +3259,7 @@ ExecutionContext* RTCPeerConnection::GetExecutionContext() const {
}
void RTCPeerConnection::ContextDestroyed() {
+ suppress_events_ = true;
if (!closed_) {
CloseInternal();
}
@@ -3263,7 +3276,7 @@ void RTCPeerConnection::ChangeSignalingState(
signaling_state_ = signaling_state;
Event* event = Event::Create(event_type_names::kSignalingstatechange);
if (dispatch_event_immediately)
- DispatchEvent(*event);
+ MaybeDispatchEvent(event);
else
ScheduleDispatchEvent(event);
}
@@ -3306,7 +3319,8 @@ void RTCPeerConnection::ChangeIceConnectionState(
return;
}
ice_connection_state_ = ice_connection_state;
- DispatchEvent(*Event::Create(event_type_names::kIceconnectionstatechange));
+ MaybeDispatchEvent(
+ Event::Create(event_type_names::kIceconnectionstatechange));
}
webrtc::PeerConnectionInterface::IceConnectionState
@@ -3431,12 +3445,30 @@ void RTCPeerConnection::CloseInternal() {
feature_handle_for_scheduler_.reset();
}
+void RTCPeerConnection::MaybeDispatchEvent(Event* event) {
+ if (suppress_events_)
+ return;
+ DispatchEvent(*event);
+}
+
void RTCPeerConnection::ScheduleDispatchEvent(Event* event) {
ScheduleDispatchEvent(event, BoolFunction());
}
void RTCPeerConnection::ScheduleDispatchEvent(Event* event,
BoolFunction setup_function) {
+ if (peer_handler_unregistered_) {
+ DCHECK(scheduled_events_.IsEmpty())
+ << "Undelivered events can cause memory leaks due to "
+ << "WrapPersistent(this) in setup function callbacks";
+ return;
+ }
+ if (suppress_events_) {
+ // If suppressed due to closing we also want to ignore the event, but we
+ // don't need to crash.
+ return;
+ }
+
scheduled_events_.push_back(
MakeGarbageCollected<EventWrapper>(event, std::move(setup_function)));
@@ -3444,6 +3476,13 @@ void RTCPeerConnection::ScheduleDispatchEvent(Event* event,
return;
if (auto* context = GetExecutionContext()) {
+ if (dispatch_events_task_created_callback_for_testing_) {
+ context->GetTaskRunner(TaskType::kNetworking)
+ ->PostTask(
+ FROM_HERE,
+ std::move(dispatch_events_task_created_callback_for_testing_));
+ }
+
// WebRTC spec specifies kNetworking as task source.
// https://www.w3.org/TR/webrtc/#operation
dispatch_scheduled_events_task_handle_ = PostCancellableTask(
@@ -3454,8 +3493,17 @@ void RTCPeerConnection::ScheduleDispatchEvent(Event* event,
}
void RTCPeerConnection::DispatchScheduledEvents() {
- if (stopped_)
+ if (peer_handler_unregistered_) {
+ DCHECK(scheduled_events_.IsEmpty())
+ << "Undelivered events can cause memory leaks due to "
+ << "WrapPersistent(this) in setup function callbacks";
+ return;
+ }
+ if (suppress_events_) {
+ // If suppressed due to closing we also want to ignore the event, but we
+ // don't need to crash.
return;
+ }
HeapVector<Member<EventWrapper>> events;
events.swap(scheduled_events_);
@@ -3470,7 +3518,7 @@ void RTCPeerConnection::DispatchScheduledEvents() {
events.clear();
}
-void RTCPeerConnection::Trace(Visitor* visitor) {
+void RTCPeerConnection::Trace(Visitor* visitor) const {
visitor->Trace(tracks_);
visitor->Trace(rtp_senders_);
visitor->Trace(rtp_receivers_);