diff --git a/api/BUILD.gn b/api/BUILD.gn index b48247ce0f..f6c28f81f4 100644 --- a/api/BUILD.gn +++ b/api/BUILD.gn @@ -1010,6 +1010,7 @@ if (rtc_include_tests) { sources = [ "test/compile_all_headers.cc" ] deps = [ + ":dummy_peer_connection", ":fake_frame_decryptor", ":fake_frame_encryptor", ":fake_media_transport", diff --git a/api/peer_connection_interface.h b/api/peer_connection_interface.h index cc37dabd65..0ae47b2a2f 100644 --- a/api/peer_connection_interface.h +++ b/api/peer_connection_interface.h @@ -1109,6 +1109,13 @@ class RTC_EXPORT PeerConnectionInterface : public rtc::RefCountInterface { virtual IceGatheringState ice_gathering_state() = 0; + // Returns the current state of canTrickleIceCandidates per + // https://w3c.github.io/webrtc-pc/#attributes-1 + virtual absl::optional can_trickle_ice_candidates() { + // TODO(crbug.com/708484): Remove default implementation. + return absl::nullopt; + } + // Start RtcEventLog using an existing output-sink. Takes ownership of // |output| and passes it on to Call, which will take the ownership. If the // operation fails the output will be closed and deallocated. The event log diff --git a/api/peer_connection_proxy.h b/api/peer_connection_proxy.h index 1b4ceeaeff..c278308ccb 100644 --- a/api/peer_connection_proxy.h +++ b/api/peer_connection_proxy.h @@ -131,6 +131,7 @@ PROXY_METHOD0(IceConnectionState, ice_connection_state) PROXY_METHOD0(IceConnectionState, standardized_ice_connection_state) PROXY_METHOD0(PeerConnectionState, peer_connection_state) PROXY_METHOD0(IceGatheringState, ice_gathering_state) +PROXY_METHOD0(absl::optional, can_trickle_ice_candidates) PROXY_METHOD2(bool, StartRtcEventLog, std::unique_ptr, diff --git a/api/test/dummy_peer_connection.h b/api/test/dummy_peer_connection.h index fcd91e3e2f..102b0684c0 100644 --- a/api/test/dummy_peer_connection.h +++ b/api/test/dummy_peer_connection.h @@ -229,6 +229,8 @@ class DummyPeerConnection : public PeerConnectionInterface { return IceGatheringState(); } + absl::optional can_trickle_ice_candidates() { return absl::nullopt; } + bool StartRtcEventLog(std::unique_ptr output, int64_t output_period_ms) override { return false; diff --git a/api/test/mock_peerconnectioninterface.h b/api/test/mock_peerconnectioninterface.h index aacaaf6cab..4e0a74e015 100644 --- a/api/test/mock_peerconnectioninterface.h +++ b/api/test/mock_peerconnectioninterface.h @@ -127,6 +127,7 @@ class MockPeerConnectionInterface MOCK_METHOD0(standardized_ice_connection_state, IceConnectionState()); MOCK_METHOD0(peer_connection_state, PeerConnectionState()); MOCK_METHOD0(ice_gathering_state, IceGatheringState()); + MOCK_METHOD0(can_trickle_ice_candidates, absl::optional()); MOCK_METHOD2(StartRtcEventLog, bool(std::unique_ptr, int64_t)); MOCK_METHOD1(StartRtcEventLog, bool(std::unique_ptr)); diff --git a/pc/peer_connection.cc b/pc/peer_connection.cc index 6678552a42..5fccf1f7f2 100644 --- a/pc/peer_connection.cc +++ b/pc/peer_connection.cc @@ -2144,6 +2144,23 @@ PeerConnection::ice_gathering_state() { return ice_gathering_state_; } +absl::optional PeerConnection::can_trickle_ice_candidates() { + RTC_DCHECK_RUN_ON(signaling_thread()); + SessionDescriptionInterface* description = current_remote_description_.get(); + if (!description) { + description = pending_remote_description_.get(); + } + if (!description) { + return absl::nullopt; + } + // TODO(bugs.webrtc.org/7443): Change to retrieve from session-level option. + if (description->description()->transport_infos().size() < 1) { + return absl::nullopt; + } + return description->description()->transport_infos()[0].description.HasOption( + "trickle"); +} + rtc::scoped_refptr PeerConnection::CreateDataChannel( const std::string& label, const DataChannelInit* config) { diff --git a/pc/peer_connection.h b/pc/peer_connection.h index 822930b58d..cd5c00116a 100644 --- a/pc/peer_connection.h +++ b/pc/peer_connection.h @@ -189,6 +189,7 @@ class PeerConnection : public PeerConnectionInternal, IceConnectionState standardized_ice_connection_state() override; PeerConnectionState peer_connection_state() override; IceGatheringState ice_gathering_state() override; + absl::optional can_trickle_ice_candidates() override; const SessionDescriptionInterface* local_description() const override; const SessionDescriptionInterface* remote_description() const override; diff --git a/pc/peer_connection_interface_unittest.cc b/pc/peer_connection_interface_unittest.cc index 8db8751b64..2a36970597 100644 --- a/pc/peer_connection_interface_unittest.cc +++ b/pc/peer_connection_interface_unittest.cc @@ -3485,7 +3485,10 @@ TEST_P(PeerConnectionInterfaceTest, OffersAndAnswersHaveTrickleIceOption) { EXPECT_TRUE(desc->transport_infos()[1].description.HasOption("trickle")); // Apply the offer as a remote description, then create an answer. + EXPECT_FALSE(pc_->can_trickle_ice_candidates()); EXPECT_TRUE(DoSetRemoteDescription(std::move(offer))); + ASSERT_TRUE(pc_->can_trickle_ice_candidates()); + EXPECT_TRUE(*(pc_->can_trickle_ice_candidates())); std::unique_ptr answer; ASSERT_TRUE(DoCreateAnswer(&answer, &options)); desc = answer->description(); diff --git a/pc/test/fake_peer_connection_base.h b/pc/test/fake_peer_connection_base.h index 238013cb9b..f4b27f03e1 100644 --- a/pc/test/fake_peer_connection_base.h +++ b/pc/test/fake_peer_connection_base.h @@ -217,6 +217,8 @@ class FakePeerConnectionBase : public PeerConnectionInternal { return IceGatheringState::kIceGatheringNew; } + absl::optional can_trickle_ice_candidates() { return absl::nullopt; } + bool StartRtcEventLog(std::unique_ptr output, int64_t output_period_ms) override { return false;