Allow to provide prebuild Environment to construct PeerConnectionFactory

That would allow to share the Environment across PeerConnectionFactory
and its injected dependencies, e.g. AudioDeviceModuel

Bug: webrtc:413413572
Change-Id: Ic99a2e39664e224a3d63e73ba8e584cbee838bfd
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/388140
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Owners-Override: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#44473}
diff --git a/api/BUILD.gn b/api/BUILD.gn
index 7a35918..6340d2b 100644
--- a/api/BUILD.gn
+++ b/api/BUILD.gn
@@ -366,6 +366,7 @@
     "crypto:frame_decryptor_interface",
     "crypto:frame_encryptor_interface",
     "crypto:options",
+    "environment",
     "metronome",
     "neteq:neteq_api",
     "rtc_event_log:rtc_event_log_factory_interface",
diff --git a/api/peer_connection_interface.h b/api/peer_connection_interface.h
index de071d5..bffbf07 100644
--- a/api/peer_connection_interface.h
+++ b/api/peer_connection_interface.h
@@ -92,6 +92,7 @@
 #include "api/data_channel_event_observer_interface.h"
 #include "api/data_channel_interface.h"
 #include "api/dtls_transport_interface.h"
+#include "api/environment/environment.h"
 #include "api/fec_controller.h"
 #include "api/field_trials_view.h"
 #include "api/ice_transport_interface.h"
@@ -1430,9 +1431,18 @@
   Thread* worker_thread = nullptr;
   Thread* signaling_thread = nullptr;
   SocketFactory* socket_factory = nullptr;
+
+  // Provides common widely used dependencies for webrtc subcomponents.
+  // `task_queue_factory` and `field_trials` members below override values in
+  // `env` when set.
+  std::optional<Environment> env;
+
   // The `packet_socket_factory` will only be used if CreatePeerConnection is
   // called without a `port_allocator`.
   std::unique_ptr<PacketSocketFactory> packet_socket_factory;
+  // Deprecated. Instead provide custom task queue factory through the `env`.
+  // TODO: bugs.webrtc.org/42220378 - Mark [[deprecated]] once unused in WebRTC
+  // and chromium
   std::unique_ptr<TaskQueueFactory> task_queue_factory;
   std::unique_ptr<RtcEventLogFactoryInterface> event_log_factory;
   std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory;
@@ -1448,6 +1458,9 @@
   std::unique_ptr<NetworkMonitorFactory> network_monitor_factory;
   std::unique_ptr<NetEqFactory> neteq_factory;
   std::unique_ptr<SctpTransportFactoryInterface> sctp_factory;
+  // Deprecated. Instead provide custom field trials through the `env`.
+  // TODO: bugs.webrtc.org/42220378 - Mark [[deprecated]] once unused in WebRTC
+  // and chromium
   std::unique_ptr<FieldTrialsView> trials;
   std::unique_ptr<RtpTransportControllerSendFactoryInterface>
       transport_controller_send_factory;
diff --git a/pc/peer_connection_factory.cc b/pc/peer_connection_factory.cc
index e62d25a..d23aec1 100644
--- a/pc/peer_connection_factory.cc
+++ b/pc/peer_connection_factory.cc
@@ -13,6 +13,7 @@
 #include <cstdint>
 #include <cstdio>
 #include <memory>
+#include <optional>
 #include <string>
 #include <utility>
 #include <vector>
@@ -67,6 +68,25 @@
 #include "rtc_base/system/file_wrapper.h"
 
 namespace webrtc {
+namespace {
+
+Environment AssembleEnvironment(PeerConnectionFactoryDependencies& deps) {
+  // Assemble Environment here rather than in ConnectionContext::Create
+  // to avoid dependency on EnvironmentFactory by ConnectionContext and thus its
+  // users.
+  EnvironmentFactory env_factory = deps.env.has_value()
+                                       ? EnvironmentFactory(*deps.env)
+                                       : EnvironmentFactory();
+  env_factory.Set(std::move(deps.trials));
+  env_factory.Set(std::move(deps.task_queue_factory));
+
+  // Clear Environment from `deps` to avoid accidental usage of the wrong
+  // Environment.
+  deps.env = std::nullopt;
+  return env_factory.Create();
+}
+
+}  // namespace
 
 scoped_refptr<PeerConnectionFactoryInterface>
 CreateModularPeerConnectionFactory(
@@ -93,10 +113,8 @@
 // Static
 scoped_refptr<PeerConnectionFactory> PeerConnectionFactory::Create(
     PeerConnectionFactoryDependencies dependencies) {
-  auto context = ConnectionContext::Create(
-      CreateEnvironment(std::move(dependencies.trials),
-                        std::move(dependencies.task_queue_factory)),
-      &dependencies);
+  auto context = ConnectionContext::Create(AssembleEnvironment(dependencies),
+                                           &dependencies);
   if (!context) {
     return nullptr;
   }
@@ -128,10 +146,8 @@
 PeerConnectionFactory::PeerConnectionFactory(
     PeerConnectionFactoryDependencies dependencies)
     : PeerConnectionFactory(
-          ConnectionContext::Create(
-              CreateEnvironment(std::move(dependencies.trials),
-                                std::move(dependencies.task_queue_factory)),
-              &dependencies),
+          ConnectionContext::Create(AssembleEnvironment(dependencies),
+                                    &dependencies),
           &dependencies) {}
 
 PeerConnectionFactory::~PeerConnectionFactory() {
diff --git a/pc/peer_connection_factory_unittest.cc b/pc/peer_connection_factory_unittest.cc
index f895496..aeb7987 100644
--- a/pc/peer_connection_factory_unittest.cc
+++ b/pc/peer_connection_factory_unittest.cc
@@ -25,6 +25,8 @@
 #include "api/enable_media.h"
 #include "api/enable_media_with_defaults.h"
 #include "api/environment/environment_factory.h"
+#include "api/field_trials.h"
+#include "api/field_trials_view.h"
 #include "api/jsep.h"
 #include "api/make_ref_counted.h"
 #include "api/media_stream_interface.h"
@@ -32,7 +34,6 @@
 #include "api/peer_connection_interface.h"
 #include "api/rtp_parameters.h"
 #include "api/scoped_refptr.h"
-#include "api/task_queue/default_task_queue_factory.h"
 #include "api/test/mock_packet_socket_factory.h"
 #include "api/units/time_delta.h"
 #include "api/video_codecs/scalability_mode.h"
@@ -80,6 +81,7 @@
 using ::testing::AtLeast;
 using ::testing::InvokeWithoutArgs;
 using ::testing::NiceMock;
+using ::testing::NotNull;
 using ::testing::Return;
 using ::testing::UnorderedElementsAre;
 using ::webrtc::test::MockAudioProcessing;
@@ -275,7 +277,6 @@
   pcf_dependencies.signaling_thread = Thread::Current();
   pcf_dependencies.worker_thread = Thread::Current();
   pcf_dependencies.network_thread = Thread::Current();
-  pcf_dependencies.task_queue_factory = CreateDefaultTaskQueueFactory();
 
   pcf_dependencies.adm = FakeAudioCaptureModule::Create();
   pcf_dependencies.audio_encoder_factory = CreateBuiltinAudioEncoderFactory();
@@ -662,6 +663,43 @@
   EXPECT_FALSE(local_renderer.black_frame());
 }
 
+TEST(PeerConnectionFactoryDependenciesTest,
+     CanInjectFieldTrialsWithEnvironment) {
+  std::unique_ptr<FieldTrialsView> field_trials =
+      FieldTrials::CreateNoGlobal("");
+  ASSERT_THAT(field_trials, NotNull());
+  FieldTrialsView* raw_field_trials = field_trials.get();
+
+  PeerConnectionFactoryDependencies pcf_dependencies;
+  pcf_dependencies.env = CreateEnvironment(std::move(field_trials));
+  pcf_dependencies.adm = FakeAudioCaptureModule::Create();
+  EnableMediaWithDefaults(pcf_dependencies);
+
+  scoped_refptr<PeerConnectionFactory> pcf =
+      PeerConnectionFactory::Create(std::move(pcf_dependencies));
+  EXPECT_EQ(&pcf->field_trials(), raw_field_trials);
+}
+
+TEST(PeerConnectionFactoryDependenciesTest,
+     PreferFieldTrialsInjectedExplicetly) {
+  std::unique_ptr<FieldTrialsView> env_field_trials =
+      FieldTrials::CreateNoGlobal("");
+  std::unique_ptr<FieldTrialsView> explicit_field_trials =
+      FieldTrials::CreateNoGlobal("");
+  ASSERT_FALSE(env_field_trials.get() == explicit_field_trials.get());
+  FieldTrialsView* raw_explicit_field_trials = explicit_field_trials.get();
+
+  PeerConnectionFactoryDependencies pcf_dependencies;
+  pcf_dependencies.env = CreateEnvironment(std::move(env_field_trials));
+  pcf_dependencies.trials = std::move(explicit_field_trials);
+  pcf_dependencies.adm = FakeAudioCaptureModule::Create();
+  EnableMediaWithDefaults(pcf_dependencies);
+
+  scoped_refptr<PeerConnectionFactory> pcf =
+      PeerConnectionFactory::Create(std::move(pcf_dependencies));
+  EXPECT_EQ(&pcf->field_trials(), raw_explicit_field_trials);
+}
+
 TEST(PeerConnectionFactoryDependenciesTest, UsesNetworkManager) {
   constexpr TimeDelta kWaitTimeout = TimeDelta::Seconds(10);
   auto mock_network_manager = std::make_unique<NiceMock<MockNetworkManager>>();
diff --git a/sdk/objc/api/peerconnection/RTCPeerConnectionFactory+Native.h b/sdk/objc/api/peerconnection/RTCPeerConnectionFactory+Native.h
index 0873408..b11aadb 100644
--- a/sdk/objc/api/peerconnection/RTCPeerConnectionFactory+Native.h
+++ b/sdk/objc/api/peerconnection/RTCPeerConnectionFactory+Native.h
@@ -34,7 +34,7 @@
 
 /* Initialize object with provided dependencies and with media support. */
 - (instancetype)initWithMediaAndDependencies:
-    (webrtc::PeerConnectionFactoryDependencies)dependencies;
+    (webrtc::PeerConnectionFactoryDependencies &)dependencies;
 
 /* Initialize object with injectable native audio/video encoder/decoder
  * factories */
diff --git a/sdk/objc/api/peerconnection/RTCPeerConnectionFactory.mm b/sdk/objc/api/peerconnection/RTCPeerConnectionFactory.mm
index 79afe27..81eafe6 100644
--- a/sdk/objc/api/peerconnection/RTCPeerConnectionFactory.mm
+++ b/sdk/objc/api/peerconnection/RTCPeerConnectionFactory.mm
@@ -81,7 +81,7 @@
   dependencies.video_decoder_factory = webrtc::ObjCToNativeVideoDecoderFactory(
       [[RTC_OBJC_TYPE(RTCVideoDecoderFactoryH264) alloc] init]);
   dependencies.adm = [self audioDeviceModule];
-  return [self initWithMediaAndDependencies:std::move(dependencies)];
+  return [self initWithMediaAndDependencies:dependencies];
 }
 
 - (instancetype)
@@ -122,12 +122,12 @@
   } else {
     dependencies.adm = [self audioDeviceModule];
   }
-  return [self initWithMediaAndDependencies:std::move(dependencies)];
+  return [self initWithMediaAndDependencies:dependencies];
 #endif
 }
 
 - (instancetype)initWithNativeDependencies:
-    (webrtc::PeerConnectionFactoryDependencies)dependencies {
+    (webrtc::PeerConnectionFactoryDependencies &)dependencies {
   self = [super init];
   if (self) {
     _networkThread = webrtc::Thread::CreateWithSocketServer();
@@ -167,8 +167,8 @@
 }
 
 - (instancetype)initWithNoMedia {
-  return [self
-      initWithNativeDependencies:webrtc::PeerConnectionFactoryDependencies()];
+  webrtc::PeerConnectionFactoryDependencies default_deps;
+  return [self initWithNativeDependencies:default_deps];
 }
 
 - (instancetype)
@@ -198,7 +198,7 @@
     dependencies.audio_processing_builder =
         CustomAudioProcessing(std::move(audioProcessingModule));
   }
-  return [self initWithMediaAndDependencies:std::move(dependencies)];
+  return [self initWithMediaAndDependencies:dependencies];
 }
 
 - (instancetype)
@@ -232,11 +232,11 @@
         CustomAudioProcessing(std::move(audioProcessingModule));
   }
   dependencies.network_controller_factory = std::move(networkControllerFactory);
-  return [self initWithMediaAndDependencies:std::move(dependencies)];
+  return [self initWithMediaAndDependencies:dependencies];
 }
 
 - (instancetype)initWithMediaAndDependencies:
-    (webrtc::PeerConnectionFactoryDependencies)dependencies {
+    (webrtc::PeerConnectionFactoryDependencies &)dependencies {
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
   // audio_processing_builder should be used instead in new code.
@@ -254,7 +254,7 @@
         std::make_unique<webrtc::RtcEventLogFactory>();
   }
   webrtc::EnableMedia(dependencies);
-  return [self initWithNativeDependencies:std::move(dependencies)];
+  return [self initWithNativeDependencies:dependencies];
 }
 
 - (RTC_OBJC_TYPE(RTCRtpCapabilities) *)rtpSenderCapabilitiesForKind:
diff --git a/sdk/objc/api/peerconnection/RTCPeerConnectionFactoryBuilder.mm b/sdk/objc/api/peerconnection/RTCPeerConnectionFactoryBuilder.mm
index 8fe5565..3485dc8 100644
--- a/sdk/objc/api/peerconnection/RTCPeerConnectionFactoryBuilder.mm
+++ b/sdk/objc/api/peerconnection/RTCPeerConnectionFactoryBuilder.mm
@@ -28,7 +28,7 @@
 
 - (RTC_OBJC_TYPE(RTCPeerConnectionFactory) *)createPeerConnectionFactory {
   return [[RTC_OBJC_TYPE(RTCPeerConnectionFactory) alloc]
-      initWithMediaAndDependencies:std::move(_dependencies)];
+      initWithMediaAndDependencies:_dependencies];
 }
 
 - (void)setFieldTrials:(std::unique_ptr<webrtc::FieldTrialsView>)fieldTrials {
diff --git a/sdk/objc/unittests/RTCPeerConnectionFactoryBuilderTest.mm b/sdk/objc/unittests/RTCPeerConnectionFactoryBuilderTest.mm
index 95d8b05..929490b 100644
--- a/sdk/objc/unittests/RTCPeerConnectionFactoryBuilderTest.mm
+++ b/sdk/objc/unittests/RTCPeerConnectionFactoryBuilderTest.mm
@@ -40,9 +40,9 @@
   id factoryMock =
       OCMStrictClassMock([RTC_OBJC_TYPE(RTCPeerConnectionFactory) class]);
   OCMExpect([factoryMock alloc]).andReturn(factoryMock);
+  webrtc::PeerConnectionFactoryDependencies default_deps;
   RTC_UNUSED([[[[factoryMock expect] andReturn:factoryMock]
-      ignoringNonObjectArgs] initWithMediaAndDependencies:
-                                 webrtc::PeerConnectionFactoryDependencies()]);
+      ignoringNonObjectArgs] initWithMediaAndDependencies:default_deps]);
   RTCPeerConnectionFactoryBuilder* builder =
       [[RTCPeerConnectionFactoryBuilder alloc] init];
   RTC_OBJC_TYPE(RTCPeerConnectionFactory)* peerConnectionFactory =
@@ -55,9 +55,9 @@
   id factoryMock =
       OCMStrictClassMock([RTC_OBJC_TYPE(RTCPeerConnectionFactory) class]);
   OCMExpect([factoryMock alloc]).andReturn(factoryMock);
+  webrtc::PeerConnectionFactoryDependencies default_deps;
   RTC_UNUSED([[[[factoryMock expect] andReturn:factoryMock]
-      ignoringNonObjectArgs] initWithMediaAndDependencies:
-                                 webrtc::PeerConnectionFactoryDependencies()]);
+      ignoringNonObjectArgs] initWithMediaAndDependencies:default_deps]);
   RTCPeerConnectionFactoryBuilder* builder =
       [RTCPeerConnectionFactoryBuilder defaultBuilder];
   RTC_OBJC_TYPE(RTCPeerConnectionFactory)* peerConnectionFactory =
diff --git a/tools_webrtc/iwyu/iwyu-verifier-filter_list.json b/tools_webrtc/iwyu/iwyu-verifier-filter_list.json
index 9cd95be..364d2c8 100644
--- a/tools_webrtc/iwyu/iwyu-verifier-filter_list.json
+++ b/tools_webrtc/iwyu/iwyu-verifier-filter_list.json
@@ -9,6 +9,7 @@
     "modules/desktop_capture/win/",
     "rtc_base/win",
     "sdk/android/src/jni/",
+    "sdk/objc/",
     "test/ios/",
     "test/mac/"
   ]