Make ICE transports injectable.

Bug: chromium:1024965
Change-Id: I4961f50aee34c82701299f59a95cb90d231db6f5
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/158820
Commit-Queue: Qingsi Wang <qingsi@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Reviewed-by: Jonas Oreland <jonaso@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Honghai Zhang <honghaiz@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29807}
diff --git a/api/ice_transport_factory.h b/api/ice_transport_factory.h
index d981e0b..a9fd04e 100644
--- a/api/ice_transport_factory.h
+++ b/api/ice_transport_factory.h
@@ -11,48 +11,16 @@
 #ifndef API_ICE_TRANSPORT_FACTORY_H_
 #define API_ICE_TRANSPORT_FACTORY_H_
 
-#include "api/async_resolver_factory.h"
 #include "api/ice_transport_interface.h"
-#include "api/rtc_event_log/rtc_event_log.h"
 #include "api/scoped_refptr.h"
 #include "rtc_base/system/rtc_export.h"
 
 namespace cricket {
 class PortAllocator;
-}
+}  // namespace cricket
 
 namespace webrtc {
 
-struct IceTransportInit final {
- public:
-  IceTransportInit() = default;
-  IceTransportInit(const IceTransportInit&) = delete;
-  IceTransportInit(IceTransportInit&&) = default;
-  IceTransportInit& operator=(const IceTransportInit&) = delete;
-  IceTransportInit& operator=(IceTransportInit&&) = default;
-
-  cricket::PortAllocator* port_allocator() { return port_allocator_; }
-  void set_port_allocator(cricket::PortAllocator* port_allocator) {
-    port_allocator_ = port_allocator;
-  }
-
-  AsyncResolverFactory* async_resolver_factory() {
-    return async_resolver_factory_;
-  }
-  void set_async_resolver_factory(
-      AsyncResolverFactory* async_resolver_factory) {
-    async_resolver_factory_ = async_resolver_factory;
-  }
-
-  RtcEventLog* event_log() { return event_log_; }
-  void set_event_log(RtcEventLog* event_log) { event_log_ = event_log; }
-
- private:
-  cricket::PortAllocator* port_allocator_ = nullptr;
-  AsyncResolverFactory* async_resolver_factory_ = nullptr;
-  RtcEventLog* event_log_ = nullptr;
-};
-
 // Static factory for an IceTransport object that can be created
 // without using a webrtc::PeerConnection.
 // The returned object must be accessed and destroyed on the thread that
diff --git a/api/ice_transport_interface.h b/api/ice_transport_interface.h
index 6e63045..d2f1edc 100644
--- a/api/ice_transport_interface.h
+++ b/api/ice_transport_interface.h
@@ -11,12 +11,17 @@
 #ifndef API_ICE_TRANSPORT_INTERFACE_H_
 #define API_ICE_TRANSPORT_INTERFACE_H_
 
+#include <string>
+
+#include "api/async_resolver_factory.h"
 #include "api/rtc_error.h"
+#include "api/rtc_event_log/rtc_event_log.h"
 #include "api/scoped_refptr.h"
 #include "rtc_base/ref_count.h"
 
 namespace cricket {
 class IceTransportInternal;
+class PortAllocator;
 }  // namespace cricket
 
 namespace webrtc {
@@ -34,5 +39,57 @@
   virtual cricket::IceTransportInternal* internal() = 0;
 };
 
+struct IceTransportInit final {
+ public:
+  IceTransportInit() = default;
+  IceTransportInit(const IceTransportInit&) = delete;
+  IceTransportInit(IceTransportInit&&) = default;
+  IceTransportInit& operator=(const IceTransportInit&) = delete;
+  IceTransportInit& operator=(IceTransportInit&&) = default;
+
+  cricket::PortAllocator* port_allocator() { return port_allocator_; }
+  void set_port_allocator(cricket::PortAllocator* port_allocator) {
+    port_allocator_ = port_allocator;
+  }
+
+  AsyncResolverFactory* async_resolver_factory() {
+    return async_resolver_factory_;
+  }
+  void set_async_resolver_factory(
+      AsyncResolverFactory* async_resolver_factory) {
+    async_resolver_factory_ = async_resolver_factory;
+  }
+
+  RtcEventLog* event_log() { return event_log_; }
+  void set_event_log(RtcEventLog* event_log) { event_log_ = event_log; }
+
+ private:
+  cricket::PortAllocator* port_allocator_ = nullptr;
+  AsyncResolverFactory* async_resolver_factory_ = nullptr;
+  RtcEventLog* event_log_ = nullptr;
+};
+
+// TODO(qingsi): The factory interface is defined in this file instead of its
+// namesake file ice_transport_factory.h to avoid the extra dependency on p2p/
+// introduced there by the p2p/-dependent factory methods. Move the factory
+// methods to a different file or rename it.
+class IceTransportFactory {
+ public:
+  virtual ~IceTransportFactory() = default;
+  // As a refcounted object, the returned ICE transport may outlive the host
+  // construct into which its reference is given, e.g. a peer connection. As a
+  // result, the returned ICE transport should not hold references to any object
+  // that the transport does not own and that has a lifetime bound to the host
+  // construct. Also, assumptions on the thread safety of the returned transport
+  // should be clarified by implementations. For example, a peer connection
+  // requires the returned transport to be constructed and destroyed on the
+  // network thread and an ICE transport factory that intends to work with a
+  // peer connection should offer transports compatible with these assumptions.
+  virtual rtc::scoped_refptr<IceTransportInterface> CreateIceTransport(
+      const std::string& transport_name,
+      int component,
+      IceTransportInit init) = 0;
+};
+
 }  // namespace webrtc
 #endif  // API_ICE_TRANSPORT_INTERFACE_H_
diff --git a/api/peer_connection_interface.h b/api/peer_connection_interface.h
index a1280de..f2ef336 100644
--- a/api/peer_connection_interface.h
+++ b/api/peer_connection_interface.h
@@ -83,6 +83,7 @@
 #include "api/data_channel_interface.h"
 #include "api/dtls_transport_interface.h"
 #include "api/fec_controller.h"
+#include "api/ice_transport_interface.h"
 #include "api/jsep.h"
 #include "api/media_stream_interface.h"
 #include "api/neteq/neteq_factory.h"
@@ -1288,6 +1289,7 @@
   std::unique_ptr<cricket::PortAllocator> allocator;
   std::unique_ptr<rtc::PacketSocketFactory> packet_socket_factory;
   std::unique_ptr<webrtc::AsyncResolverFactory> async_resolver_factory;
+  std::unique_ptr<webrtc::IceTransportFactory> ice_transport_factory;
   std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator;
   std::unique_ptr<rtc::SSLCertificateVerifier> tls_cert_verifier;
   std::unique_ptr<webrtc::VideoBitrateAllocatorFactory>
diff --git a/p2p/BUILD.gn b/p2p/BUILD.gn
index 8c4b6f6..42afcff 100644
--- a/p2p/BUILD.gn
+++ b/p2p/BUILD.gn
@@ -41,8 +41,11 @@
     "base/connection.h",
     "base/connection_info.cc",
     "base/connection_info.h",
+    "base/default_ice_transport_factory.cc",
+    "base/default_ice_transport_factory.h",
     "base/dtls_transport.cc",
     "base/dtls_transport.h",
+    "base/dtls_transport_factory.h",
     "base/dtls_transport_internal.cc",
     "base/dtls_transport_internal.h",
     "base/ice_credentials_iterator.cc",
@@ -80,7 +83,6 @@
     "base/transport_description.h",
     "base/transport_description_factory.cc",
     "base/transport_description_factory.h",
-    "base/transport_factory_interface.h",
     "base/transport_info.h",
     "base/turn_port.cc",
     "base/turn_port.h",
@@ -132,6 +134,7 @@
     ]
     deps = [
       ":rtc_p2p",
+      "../api:libjingle_peerconnection_api",
       "../rtc_base",
       "../rtc_base:rtc_base_approved",
       "//third_party/abseil-cpp/absl/algorithm:container",
diff --git a/p2p/base/default_ice_transport_factory.cc b/p2p/base/default_ice_transport_factory.cc
new file mode 100644
index 0000000..4430525
--- /dev/null
+++ b/p2p/base/default_ice_transport_factory.cc
@@ -0,0 +1,36 @@
+/*
+ *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "p2p/base/default_ice_transport_factory.h"
+
+#include <utility>
+
+namespace webrtc {
+
+DefaultIceTransport::DefaultIceTransport(
+    std::unique_ptr<cricket::P2PTransportChannel> internal)
+    : internal_(std::move(internal)) {}
+
+DefaultIceTransport::~DefaultIceTransport() {
+  RTC_DCHECK_RUN_ON(&thread_checker_);
+}
+
+rtc::scoped_refptr<IceTransportInterface>
+DefaultIceTransportFactory::CreateIceTransport(
+    const std::string& transport_name,
+    int component,
+    IceTransportInit init) {
+  return new rtc::RefCountedObject<DefaultIceTransport>(
+      std::make_unique<cricket::P2PTransportChannel>(
+          transport_name, component, init.port_allocator(),
+          init.async_resolver_factory(), init.event_log()));
+}
+
+}  // namespace webrtc
diff --git a/p2p/base/default_ice_transport_factory.h b/p2p/base/default_ice_transport_factory.h
new file mode 100644
index 0000000..4834c9a
--- /dev/null
+++ b/p2p/base/default_ice_transport_factory.h
@@ -0,0 +1,58 @@
+/*
+ *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef P2P_BASE_DEFAULT_ICE_TRANSPORT_FACTORY_H_
+#define P2P_BASE_DEFAULT_ICE_TRANSPORT_FACTORY_H_
+
+#include <memory>
+#include <string>
+
+#include "api/ice_transport_interface.h"
+#include "p2p/base/p2p_transport_channel.h"
+#include "rtc_base/thread.h"
+
+namespace webrtc {
+
+// The default ICE transport wraps the implementation of IceTransportInternal
+// provided by P2PTransportChannel. This default transport is not thread safe
+// and must be constructed, used and destroyed on the same network thread on
+// which the internal P2PTransportChannel lives.
+class DefaultIceTransport : public IceTransportInterface {
+ public:
+  explicit DefaultIceTransport(
+      std::unique_ptr<cricket::P2PTransportChannel> internal);
+  ~DefaultIceTransport();
+
+  cricket::IceTransportInternal* internal() override {
+    RTC_DCHECK_RUN_ON(&thread_checker_);
+    return internal_.get();
+  }
+
+ private:
+  const rtc::ThreadChecker thread_checker_{};
+  std::unique_ptr<cricket::P2PTransportChannel> internal_
+      RTC_GUARDED_BY(thread_checker_);
+};
+
+class DefaultIceTransportFactory : public IceTransportFactory {
+ public:
+  DefaultIceTransportFactory() = default;
+  ~DefaultIceTransportFactory() = default;
+
+  // Must be called on the network thread and returns a DefaultIceTransport.
+  rtc::scoped_refptr<IceTransportInterface> CreateIceTransport(
+      const std::string& transport_name,
+      int component,
+      IceTransportInit init) override;
+};
+
+}  // namespace webrtc
+
+#endif  // P2P_BASE_DEFAULT_ICE_TRANSPORT_FACTORY_H_
diff --git a/p2p/base/dtls_transport_factory.h b/p2p/base/dtls_transport_factory.h
new file mode 100644
index 0000000..9ad78a7
--- /dev/null
+++ b/p2p/base/dtls_transport_factory.h
@@ -0,0 +1,39 @@
+/*
+ *  Copyright 2018 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef P2P_BASE_DTLS_TRANSPORT_FACTORY_H_
+#define P2P_BASE_DTLS_TRANSPORT_FACTORY_H_
+
+#include <memory>
+#include <string>
+
+#include "p2p/base/dtls_transport_internal.h"
+#include "p2p/base/ice_transport_internal.h"
+
+namespace cricket {
+
+// This interface is used to create DTLS transports. The external transports
+// can be injected into the JsepTransportController through it.
+//
+// TODO(qingsi): Remove this factory in favor of one that produces
+// DtlsTransportInterface given by the public API if this is going to be
+// injectable.
+class DtlsTransportFactory {
+ public:
+  virtual ~DtlsTransportFactory() = default;
+
+  virtual std::unique_ptr<DtlsTransportInternal> CreateDtlsTransport(
+      IceTransportInternal* ice,
+      const webrtc::CryptoOptions& crypto_options) = 0;
+};
+
+}  // namespace cricket
+
+#endif  // P2P_BASE_DTLS_TRANSPORT_FACTORY_H_
diff --git a/p2p/base/fake_ice_transport.h b/p2p/base/fake_ice_transport.h
index b1a83b8..d0fa1ea 100644
--- a/p2p/base/fake_ice_transport.h
+++ b/p2p/base/fake_ice_transport.h
@@ -12,11 +12,13 @@
 #define P2P_BASE_FAKE_ICE_TRANSPORT_H_
 
 #include <map>
+#include <memory>
 #include <string>
 #include <utility>
 
 #include "absl/algorithm/container.h"
 #include "absl/types/optional.h"
+#include "api/ice_transport_interface.h"
 #include "p2p/base/ice_transport_internal.h"
 #include "rtc_base/async_invoker.h"
 #include "rtc_base/copy_on_write_buffer.h"
@@ -330,6 +332,18 @@
   rtc::Thread* const network_thread_;
 };
 
+class FakeIceTransportWrapper : public webrtc::IceTransportInterface {
+ public:
+  explicit FakeIceTransportWrapper(
+      std::unique_ptr<cricket::FakeIceTransport> internal)
+      : internal_(std::move(internal)) {}
+
+  cricket::IceTransportInternal* internal() override { return internal_.get(); }
+
+ private:
+  std::unique_ptr<cricket::FakeIceTransport> internal_;
+};
+
 }  // namespace cricket
 
 #endif  // P2P_BASE_FAKE_ICE_TRANSPORT_H_
diff --git a/p2p/base/transport_factory_interface.h b/p2p/base/transport_factory_interface.h
deleted file mode 100644
index e7eead7..0000000
--- a/p2p/base/transport_factory_interface.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *  Copyright 2018 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#ifndef P2P_BASE_TRANSPORT_FACTORY_INTERFACE_H_
-#define P2P_BASE_TRANSPORT_FACTORY_INTERFACE_H_
-
-#include <memory>
-#include <string>
-
-#include "p2p/base/dtls_transport_internal.h"
-#include "p2p/base/ice_transport_internal.h"
-
-namespace cricket {
-
-// This interface is used to create DTLS/ICE transports. The external transports
-// can be injected into the JsepTransportController through it. For example, the
-// FakeIceTransport/FakeDtlsTransport can be injected by setting a
-// FakeTransportFactory which implements this interface to the
-// JsepTransportController.
-class TransportFactoryInterface {
- public:
-  virtual ~TransportFactoryInterface() {}
-
-  virtual std::unique_ptr<IceTransportInternal> CreateIceTransport(
-      const std::string& transport_name,
-      int component) = 0;
-
-  virtual std::unique_ptr<DtlsTransportInternal> CreateDtlsTransport(
-      IceTransportInternal* ice,
-      const webrtc::CryptoOptions& crypto_options) = 0;
-};
-
-}  // namespace cricket
-
-#endif  // P2P_BASE_TRANSPORT_FACTORY_INTERFACE_H_
diff --git a/pc/BUILD.gn b/pc/BUILD.gn
index 2dcbd91..40f3b50 100644
--- a/pc/BUILD.gn
+++ b/pc/BUILD.gn
@@ -87,6 +87,7 @@
     "../api:array_view",
     "../api:audio_options_api",
     "../api:call_api",
+    "../api:ice_transport_factory",
     "../api:libjingle_peerconnection_api",
     "../api:rtc_error",
     "../api:rtp_headers",
@@ -227,6 +228,7 @@
     "../api:audio_options_api",
     "../api:call_api",
     "../api:fec_controller_api",
+    "../api:ice_transport_factory",
     "../api:libjingle_peerconnection_api",
     "../api:media_stream_interface",
     "../api:network_state_predictor_api",
@@ -577,6 +579,7 @@
       "../modules/audio_device:audio_device_api",
       "../modules/audio_processing:audio_processing_statistics",
       "../modules/rtp_rtcp:rtp_rtcp_format",
+      "../p2p:fake_ice_transport",
       "../p2p:fake_port_allocator",
       "../rtc_base:checks",
       "../rtc_base:gunit_helpers",
diff --git a/pc/jsep_transport.cc b/pc/jsep_transport.cc
index 13618c7..79b933c 100644
--- a/pc/jsep_transport.cc
+++ b/pc/jsep_transport.cc
@@ -102,8 +102,8 @@
 JsepTransport::JsepTransport(
     const std::string& mid,
     const rtc::scoped_refptr<rtc::RTCCertificate>& local_certificate,
-    std::unique_ptr<cricket::IceTransportInternal> ice_transport,
-    std::unique_ptr<cricket::IceTransportInternal> rtcp_ice_transport,
+    rtc::scoped_refptr<webrtc::IceTransportInterface> ice_transport,
+    rtc::scoped_refptr<webrtc::IceTransportInterface> rtcp_ice_transport,
     std::unique_ptr<webrtc::RtpTransport> unencrypted_rtp_transport,
     std::unique_ptr<webrtc::SrtpTransport> sdes_transport,
     std::unique_ptr<webrtc::DtlsSrtpTransport> dtls_srtp_transport,
diff --git a/pc/jsep_transport.h b/pc/jsep_transport.h
index 3c63c47..658e8e7 100644
--- a/pc/jsep_transport.h
+++ b/pc/jsep_transport.h
@@ -18,6 +18,7 @@
 
 #include "absl/types/optional.h"
 #include "api/candidate.h"
+#include "api/ice_transport_interface.h"
 #include "api/jsep.h"
 #include "api/transport/datagram_transport_interface.h"
 #include "api/transport/media/media_transport_interface.h"
@@ -101,8 +102,8 @@
   JsepTransport(
       const std::string& mid,
       const rtc::scoped_refptr<rtc::RTCCertificate>& local_certificate,
-      std::unique_ptr<cricket::IceTransportInternal> ice_transport,
-      std::unique_ptr<cricket::IceTransportInternal> rtcp_ice_transport,
+      rtc::scoped_refptr<webrtc::IceTransportInterface> ice_transport,
+      rtc::scoped_refptr<webrtc::IceTransportInterface> rtcp_ice_transport,
       std::unique_ptr<webrtc::RtpTransport> unencrypted_rtp_transport,
       std::unique_ptr<webrtc::SrtpTransport> sdes_transport,
       std::unique_ptr<webrtc::DtlsSrtpTransport> dtls_srtp_transport,
@@ -377,8 +378,8 @@
 
   // Ice transport which may be used by any of upper-layer transports (below).
   // Owned by JsepTransport and guaranteed to outlive the transports below.
-  const std::unique_ptr<cricket::IceTransportInternal> ice_transport_;
-  const std::unique_ptr<cricket::IceTransportInternal> rtcp_ice_transport_;
+  const rtc::scoped_refptr<webrtc::IceTransportInterface> ice_transport_;
+  const rtc::scoped_refptr<webrtc::IceTransportInterface> rtcp_ice_transport_;
 
   // To avoid downcasting and make it type safe, keep three unique pointers for
   // different SRTP mode and only one of these is non-nullptr.
diff --git a/pc/jsep_transport_controller.cc b/pc/jsep_transport_controller.cc
index d83b16e..41907c8 100644
--- a/pc/jsep_transport_controller.cc
+++ b/pc/jsep_transport_controller.cc
@@ -14,6 +14,7 @@
 #include <utility>
 
 #include "absl/algorithm/container.h"
+#include "api/ice_transport_factory.h"
 #include "api/transport/datagram_transport_interface.h"
 #include "api/transport/media/media_transport_interface.h"
 #include "p2p/base/ice_transport_internal.h"
@@ -90,6 +91,7 @@
   // The |transport_observer| is assumed to be non-null.
   RTC_DCHECK(config_.transport_observer);
   RTC_DCHECK(config_.rtcp_handler);
+  RTC_DCHECK(config_.ice_transport_factory);
 }
 
 JsepTransportController::~JsepTransportController() {
@@ -481,20 +483,18 @@
   MaybeDestroyJsepTransport(mid);
 }
 
-std::unique_ptr<cricket::IceTransportInternal>
-JsepTransportController::CreateIceTransport(const std::string transport_name,
+rtc::scoped_refptr<webrtc::IceTransportInterface>
+JsepTransportController::CreateIceTransport(const std::string& transport_name,
                                             bool rtcp) {
   int component = rtcp ? cricket::ICE_CANDIDATE_COMPONENT_RTCP
                        : cricket::ICE_CANDIDATE_COMPONENT_RTP;
 
-  if (config_.external_transport_factory) {
-    return config_.external_transport_factory->CreateIceTransport(
-        transport_name, component);
-  } else {
-    return std::make_unique<cricket::P2PTransportChannel>(
-        transport_name, component, port_allocator_, async_resolver_factory_,
-        config_.event_log);
-  }
+  IceTransportInit init;
+  init.set_port_allocator(port_allocator_);
+  init.set_async_resolver_factory(async_resolver_factory_);
+  init.set_event_log(config_.event_log);
+  return config_.ice_transport_factory->CreateIceTransport(
+      transport_name, component, std::move(init));
 }
 
 std::unique_ptr<cricket::DtlsTransportInternal>
@@ -517,8 +517,8 @@
     // Otherwise, DTLS is still created.
     dtls = std::make_unique<cricket::NoOpDtlsTransport>(ice,
                                                         config_.crypto_options);
-  } else if (config_.external_transport_factory) {
-    dtls = config_.external_transport_factory->CreateDtlsTransport(
+  } else if (config_.dtls_transport_factory) {
+    dtls = config_.dtls_transport_factory->CreateDtlsTransport(
         ice, config_.crypto_options);
   } else {
     dtls = std::make_unique<cricket::DtlsTransport>(ice, config_.crypto_options,
@@ -1250,24 +1250,25 @@
                     "SDES and DTLS-SRTP cannot be enabled at the same time.");
   }
 
-  std::unique_ptr<cricket::IceTransportInternal> ice =
+  rtc::scoped_refptr<webrtc::IceTransportInterface> ice =
       CreateIceTransport(content_info.name, /*rtcp=*/false);
+  RTC_DCHECK(ice);
 
   std::unique_ptr<MediaTransportInterface> media_transport =
       MaybeCreateMediaTransport(content_info, description, local);
   if (media_transport) {
     media_transport_created_once_ = true;
-    media_transport->Connect(ice.get());
+    media_transport->Connect(ice->internal());
   }
 
   std::unique_ptr<DatagramTransportInterface> datagram_transport =
       MaybeCreateDatagramTransport(content_info, description, local);
   if (datagram_transport) {
-    datagram_transport->Connect(ice.get());
+    datagram_transport->Connect(ice->internal());
   }
 
   std::unique_ptr<cricket::DtlsTransportInternal> rtp_dtls_transport =
-      CreateDtlsTransport(content_info, ice.get(), nullptr);
+      CreateDtlsTransport(content_info, ice->internal(), nullptr);
 
   std::unique_ptr<cricket::DtlsTransportInternal> rtcp_dtls_transport;
   std::unique_ptr<RtpTransport> unencrypted_rtp_transport;
@@ -1275,15 +1276,16 @@
   std::unique_ptr<DtlsSrtpTransport> dtls_srtp_transport;
   std::unique_ptr<RtpTransportInternal> datagram_rtp_transport;
 
-  std::unique_ptr<cricket::IceTransportInternal> rtcp_ice;
+  rtc::scoped_refptr<webrtc::IceTransportInterface> rtcp_ice;
   if (config_.rtcp_mux_policy !=
           PeerConnectionInterface::kRtcpMuxPolicyRequire &&
       content_info.type == cricket::MediaProtocolType::kRtp) {
     RTC_DCHECK(media_transport == nullptr);
     RTC_DCHECK(datagram_transport == nullptr);
     rtcp_ice = CreateIceTransport(content_info.name, /*rtcp=*/true);
-    rtcp_dtls_transport = CreateDtlsTransport(content_info, rtcp_ice.get(),
-                                              /*datagram_transport=*/nullptr);
+    rtcp_dtls_transport =
+        CreateDtlsTransport(content_info, rtcp_ice->internal(),
+                            /*datagram_transport=*/nullptr);
   }
 
   // Only create a datagram RTP transport if the datagram transport should be
@@ -1300,8 +1302,8 @@
                         "transport is used.";
     RTC_DCHECK(!rtcp_dtls_transport);
     datagram_rtp_transport = std::make_unique<DatagramRtpTransport>(
-        content_info.media_description()->rtp_header_extensions(), ice.get(),
-        datagram_transport.get());
+        content_info.media_description()->rtp_header_extensions(),
+        ice->internal(), datagram_transport.get());
   }
 
   if (config_.disable_encryption) {
diff --git a/pc/jsep_transport_controller.h b/pc/jsep_transport_controller.h
index bcaeed5..b07783c 100644
--- a/pc/jsep_transport_controller.h
+++ b/pc/jsep_transport_controller.h
@@ -19,14 +19,15 @@
 
 #include "api/candidate.h"
 #include "api/crypto/crypto_options.h"
+#include "api/ice_transport_factory.h"
 #include "api/peer_connection_interface.h"
 #include "api/rtc_event_log/rtc_event_log.h"
 #include "api/transport/media/media_transport_config.h"
 #include "api/transport/media/media_transport_interface.h"
 #include "media/sctp/sctp_transport_internal.h"
 #include "p2p/base/dtls_transport.h"
+#include "p2p/base/dtls_transport_factory.h"
 #include "p2p/base/p2p_transport_channel.h"
-#include "p2p/base/transport_factory_interface.h"
 #include "pc/channel.h"
 #include "pc/dtls_srtp_transport.h"
 #include "pc/dtls_transport.h"
@@ -91,7 +92,8 @@
     bool disable_encryption = false;
     bool enable_external_auth = false;
     // Used to inject the ICE/DTLS transports created externally.
-    cricket::TransportFactoryInterface* external_transport_factory = nullptr;
+    webrtc::IceTransportFactory* ice_transport_factory = nullptr;
+    cricket::DtlsTransportFactory* dtls_transport_factory = nullptr;
     Observer* transport_observer = nullptr;
     // Must be provided and valid for the lifetime of the
     // JsepTransportController instance.
@@ -404,8 +406,8 @@
       const cricket::ContentInfo& content_info,
       cricket::IceTransportInternal* ice,
       DatagramTransportInterface* datagram_transport);
-  std::unique_ptr<cricket::IceTransportInternal> CreateIceTransport(
-      const std::string transport_name,
+  rtc::scoped_refptr<webrtc::IceTransportInterface> CreateIceTransport(
+      const std::string& transport_name,
       bool rtcp);
 
   std::unique_ptr<webrtc::RtpTransport> CreateUnencryptedRtpTransport(
diff --git a/pc/jsep_transport_controller_unittest.cc b/pc/jsep_transport_controller_unittest.cc
index 408cb01..b96a999 100644
--- a/pc/jsep_transport_controller_unittest.cc
+++ b/pc/jsep_transport_controller_unittest.cc
@@ -16,10 +16,10 @@
 #include "api/test/fake_media_transport.h"
 #include "api/test/loopback_media_transport.h"
 #include "api/transport/media/media_transport_interface.h"
+#include "p2p/base/dtls_transport_factory.h"
 #include "p2p/base/fake_dtls_transport.h"
 #include "p2p/base/fake_ice_transport.h"
 #include "p2p/base/no_op_dtls_transport.h"
-#include "p2p/base/transport_factory_interface.h"
 #include "p2p/base/transport_info.h"
 #include "rtc_base/gunit.h"
 #include "rtc_base/thread.h"
@@ -59,15 +59,20 @@
 
 }  // namespace
 
-class FakeTransportFactory : public cricket::TransportFactoryInterface {
+class FakeIceTransportFactory : public webrtc::IceTransportFactory {
  public:
-  std::unique_ptr<cricket::IceTransportInternal> CreateIceTransport(
+  ~FakeIceTransportFactory() override = default;
+  rtc::scoped_refptr<IceTransportInterface> CreateIceTransport(
       const std::string& transport_name,
-      int component) override {
-    return std::make_unique<cricket::FakeIceTransport>(transport_name,
-                                                       component);
+      int component,
+      IceTransportInit init) override {
+    return new rtc::RefCountedObject<cricket::FakeIceTransportWrapper>(
+        std::make_unique<cricket::FakeIceTransport>(transport_name, component));
   }
+};
 
+class FakeDtlsTransportFactory : public cricket::DtlsTransportFactory {
+ public:
   std::unique_ptr<cricket::DtlsTransportInternal> CreateDtlsTransport(
       cricket::IceTransportInternal* ice,
       const webrtc::CryptoOptions& crypto_options) override {
@@ -81,7 +86,8 @@
                                     public sigslot::has_slots<> {
  public:
   JsepTransportControllerTest() : signaling_thread_(rtc::Thread::Current()) {
-    fake_transport_factory_ = std::make_unique<FakeTransportFactory>();
+    fake_ice_transport_factory_ = std::make_unique<FakeIceTransportFactory>();
+    fake_dtls_transport_factory_ = std::make_unique<FakeDtlsTransportFactory>();
   }
 
   void CreateJsepTransportController(
@@ -92,8 +98,8 @@
     config.transport_observer = this;
     config.rtcp_handler = [](const rtc::CopyOnWriteBuffer& packet,
                              int64_t packet_time_us) { RTC_NOTREACHED(); };
-    // The tests only works with |fake_transport_factory|;
-    config.external_transport_factory = fake_transport_factory_.get();
+    config.ice_transport_factory = fake_ice_transport_factory_.get();
+    config.dtls_transport_factory = fake_dtls_transport_factory_.get();
     // TODO(zstein): Provide an AsyncResolverFactory once it is required.
     transport_controller_ = std::make_unique<JsepTransportController>(
         signaling_thread, network_thread, port_allocator, nullptr, config);
@@ -358,7 +364,8 @@
 
   // |network_thread_| should be destroyed after |transport_controller_|
   std::unique_ptr<rtc::Thread> network_thread_;
-  std::unique_ptr<FakeTransportFactory> fake_transport_factory_;
+  std::unique_ptr<FakeIceTransportFactory> fake_ice_transport_factory_;
+  std::unique_ptr<FakeDtlsTransportFactory> fake_dtls_transport_factory_;
   rtc::Thread* const signaling_thread_ = nullptr;
   bool signaled_on_non_signaling_thread_ = false;
   // Used to verify the SignalRtpTransportChanged/SignalDtlsTransportChanged are
diff --git a/pc/jsep_transport_unittest.cc b/pc/jsep_transport_unittest.cc
index 00f58f6..87d6e87 100644
--- a/pc/jsep_transport_unittest.cc
+++ b/pc/jsep_transport_unittest.cc
@@ -14,12 +14,14 @@
 #include <tuple>
 #include <utility>
 
+#include "api/ice_transport_factory.h"
 #include "media/base/fake_rtp.h"
 #include "p2p/base/fake_dtls_transport.h"
 #include "p2p/base/fake_ice_transport.h"
 #include "rtc_base/gunit.h"
 
 namespace cricket {
+namespace {
 using webrtc::SdpType;
 
 static const char kIceUfrag1[] = "U001";
@@ -40,6 +42,16 @@
   SdpType remote_type;
 };
 
+rtc::scoped_refptr<webrtc::IceTransportInterface> CreateIceTransport(
+    std::unique_ptr<FakeIceTransport> internal) {
+  if (!internal) {
+    return nullptr;
+  }
+
+  return new rtc::RefCountedObject<FakeIceTransportWrapper>(
+      std::move(internal));
+}
+
 class JsepTransport2Test : public ::testing::Test, public sigslot::has_slots<> {
  protected:
   std::unique_ptr<webrtc::SrtpTransport> CreateSdesTransport(
@@ -69,17 +81,21 @@
   // FakeIceTransport.
   std::unique_ptr<JsepTransport> CreateJsepTransport2(bool rtcp_mux_enabled,
                                                       SrtpMode srtp_mode) {
-    auto ice = std::make_unique<FakeIceTransport>(kTransportName,
-                                                  ICE_CANDIDATE_COMPONENT_RTP);
-    auto rtp_dtls_transport = std::make_unique<FakeDtlsTransport>(ice.get());
+    auto ice_internal = std::make_unique<FakeIceTransport>(
+        kTransportName, ICE_CANDIDATE_COMPONENT_RTP);
+    auto rtp_dtls_transport =
+        std::make_unique<FakeDtlsTransport>(ice_internal.get());
+    auto ice = CreateIceTransport(std::move(ice_internal));
 
-    std::unique_ptr<FakeIceTransport> rtcp_ice;
+    std::unique_ptr<FakeIceTransport> rtcp_ice_internal;
     std::unique_ptr<FakeDtlsTransport> rtcp_dtls_transport;
     if (!rtcp_mux_enabled) {
-      rtcp_ice = std::make_unique<FakeIceTransport>(
+      rtcp_ice_internal = std::make_unique<FakeIceTransport>(
           kTransportName, ICE_CANDIDATE_COMPONENT_RTCP);
-      rtcp_dtls_transport = std::make_unique<FakeDtlsTransport>(rtcp_ice.get());
+      rtcp_dtls_transport =
+          std::make_unique<FakeDtlsTransport>(rtcp_ice_internal.get());
     }
+    auto rtcp_ice = CreateIceTransport(std::move(rtcp_ice_internal));
 
     std::unique_ptr<webrtc::RtpTransport> unencrypted_rtp_transport;
     std::unique_ptr<webrtc::SrtpTransport> sdes_transport;
@@ -1246,5 +1262,5 @@
         std::make_tuple(Scenario::kDtlsBeforeCallerSendOffer, false),
         std::make_tuple(Scenario::kDtlsBeforeCallerSetAnswer, false),
         std::make_tuple(Scenario::kDtlsAfterCallerSetAnswer, false)));
-
+}  // namespace
 }  // namespace cricket
diff --git a/pc/peer_connection.cc b/pc/peer_connection.cc
index ea3d8e2..1d7b4ea 100644
--- a/pc/peer_connection.cc
+++ b/pc/peer_connection.cc
@@ -1139,6 +1139,7 @@
   observer_ = dependencies.observer;
   async_resolver_factory_ = std::move(dependencies.async_resolver_factory);
   port_allocator_ = std::move(dependencies.allocator);
+  ice_transport_factory_ = std::move(dependencies.ice_transport_factory);
   tls_cert_verifier_ = std::move(dependencies.tls_cert_verifier);
 
   cricket::ServerAddresses stun_servers;
@@ -1334,6 +1335,8 @@
     }
   }
 
+  config.ice_transport_factory = ice_transport_factory_.get();
+
   transport_controller_.reset(new JsepTransportController(
       signaling_thread(), network_thread(), port_allocator_.get(),
       async_resolver_factory_.get(), config));
diff --git a/pc/peer_connection.h b/pc/peer_connection.h
index 302ff3b..cbff7e7 100644
--- a/pc/peer_connection.h
+++ b/pc/peer_connection.h
@@ -1295,6 +1295,12 @@
   std::unique_ptr<cricket::PortAllocator>
       port_allocator_;  // TODO(bugs.webrtc.org/9987): Accessed on both
                         // signaling and network thread.
+  std::unique_ptr<webrtc::IceTransportFactory>
+      ice_transport_factory_;  // TODO(bugs.webrtc.org/9987): Accessed on the
+                               // signaling thread but the underlying raw
+                               // pointer is given to
+                               // |jsep_transport_controller_| and used on the
+                               // network thread.
   std::unique_ptr<rtc::SSLCertificateVerifier>
       tls_cert_verifier_;  // TODO(bugs.webrtc.org/9987): Accessed on both
                            // signaling and network thread.
diff --git a/pc/peer_connection_factory.cc b/pc/peer_connection_factory.cc
index a1a9f04..8909ba9 100644
--- a/pc/peer_connection_factory.cc
+++ b/pc/peer_connection_factory.cc
@@ -28,6 +28,7 @@
 #include "media/base/rtp_data_engine.h"
 #include "media/sctp/sctp_transport.h"
 #include "p2p/base/basic_packet_socket_factory.h"
+#include "p2p/base/default_ice_transport_factory.h"
 #include "p2p/client/basic_port_allocator.h"
 #include "pc/audio_track.h"
 #include "pc/local_audio_source.h"
@@ -267,6 +268,11 @@
     });
   }
 
+  if (!dependencies.ice_transport_factory) {
+    dependencies.ice_transport_factory =
+        std::make_unique<DefaultIceTransportFactory>();
+  }
+
   // TODO(zstein): Once chromium injects its own AsyncResolverFactory, set
   // |dependencies.async_resolver_factory| to a new
   // |rtc::BasicAsyncResolverFactory| if no factory is provided.
diff --git a/pc/peer_connection_integrationtest.cc b/pc/peer_connection_integrationtest.cc
index 536ad01..e59ce9a 100644
--- a/pc/peer_connection_integrationtest.cc
+++ b/pc/peer_connection_integrationtest.cc
@@ -36,6 +36,7 @@
 #include "media/engine/fake_webrtc_video_engine.h"
 #include "media/engine/webrtc_media_engine.h"
 #include "media/engine/webrtc_media_engine_defaults.h"
+#include "p2p/base/fake_ice_transport.h"
 #include "p2p/base/mock_async_resolver.h"
 #include "p2p/base/p2p_constants.h"
 #include "p2p/base/port_interface.h"
@@ -1166,6 +1167,34 @@
   int callee_video_frames_expected_ = 0;
 };
 
+class MockIceTransport : public webrtc::IceTransportInterface {
+ public:
+  MockIceTransport(const std::string& name, int component)
+      : internal_(std::make_unique<cricket::FakeIceTransport>(
+            name,
+            component,
+            nullptr /* network_thread */)) {}
+  ~MockIceTransport() = default;
+  cricket::IceTransportInternal* internal() { return internal_.get(); }
+
+ private:
+  std::unique_ptr<cricket::FakeIceTransport> internal_;
+};
+
+class MockIceTransportFactory : public IceTransportFactory {
+ public:
+  ~MockIceTransportFactory() override = default;
+  rtc::scoped_refptr<IceTransportInterface> CreateIceTransport(
+      const std::string& transport_name,
+      int component,
+      IceTransportInit init) {
+    RecordIceTransportCreated();
+    return new rtc::RefCountedObject<MockIceTransport>(transport_name,
+                                                       component);
+  }
+  MOCK_METHOD0(RecordIceTransportCreated, void());
+};
+
 // Tests two PeerConnections connecting to each other end-to-end, using a
 // virtual network, fake A/V capture and fake encoder/decoders. The
 // PeerConnections share the threads/socket servers, but use separate versions
@@ -5529,6 +5558,25 @@
   EXPECT_GT(client_2_cert_verifier->call_count_, 0u);
 }
 
+// Test that the injected ICE transport factory is used to create ICE transports
+// for WebRTC connections.
+TEST_P(PeerConnectionIntegrationTest, IceTransportFactoryUsedForConnections) {
+  PeerConnectionInterface::RTCConfiguration default_config;
+  PeerConnectionDependencies dependencies(nullptr);
+  auto ice_transport_factory = std::make_unique<MockIceTransportFactory>();
+  EXPECT_CALL(*ice_transport_factory, RecordIceTransportCreated()).Times(1);
+  dependencies.ice_transport_factory = std::move(ice_transport_factory);
+  auto wrapper =
+      CreatePeerConnectionWrapper("Caller", nullptr, &default_config,
+                                  std::move(dependencies), nullptr, nullptr);
+  ASSERT_TRUE(wrapper);
+  wrapper->CreateDataChannel();
+  rtc::scoped_refptr<MockSetSessionDescriptionObserver> observer(
+      new rtc::RefCountedObject<MockSetSessionDescriptionObserver>());
+  wrapper->pc()->SetLocalDescription(observer,
+                                     wrapper->CreateOfferAndWait().release());
+}
+
 // Test that audio and video flow end-to-end when codec names don't use the
 // expected casing, given that they're supposed to be case insensitive. To test
 // this, all but one codec is removed from each media description, and its