Convert URLLoaderFactoryBundle to implement SharedURLLoaderFactory interface.

This CL also typemaps content.mojom.URLLoaderFactoryBundle to
std::unique_ptr<content::URLLoaderFactoryBundleInfo>.

This is part of the effort to avoid using raw mojom::URLLoaderFactory pointers
in renderers and also unify interface of URLLoaderFactory getters.

Bug: 796425
Change-Id: Ia30cd253ec0c82624fbf466a70da489e4464b82f
Reviewed-on: https://chromium-review.googlesource.com/877390
Commit-Queue: Yuzhu Shen <[email protected]>
Reviewed-by: Kinuko Yasuda <[email protected]>
Reviewed-by: Daniel Cheng <[email protected]>
Cr-Commit-Position: refs/heads/master@{#531318}
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 45e30e6..159ec01 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -3487,7 +3487,7 @@
     GetNavigationControl()->CommitNavigation(
         network::ResourceResponseHead(), GURL(), common_params, request_params,
         network::mojom::URLLoaderClientEndpointsPtr(),
-        /*subresource_loader_factories=*/base::nullopt,
+        /*subresource_loader_factories=*/nullptr,
         /*controller_service_worker=*/nullptr, devtools_navigation_token);
     return;
   }
@@ -3511,16 +3511,17 @@
   const bool is_same_document =
       FrameMsg_Navigate_Type::IsSameDocument(common_params.navigation_type);
 
-  base::Optional<URLLoaderFactoryBundle> subresource_loader_factories;
+  std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories;
   mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info;
   if (base::FeatureList::IsEnabled(features::kNetworkService) &&
       (!is_same_document || is_first_navigation)) {
-    subresource_loader_factories.emplace();
+    subresource_loader_factories =
+        std::make_unique<URLLoaderFactoryBundleInfo>();
     // NOTE: On Network Service navigations, we want to ensure that a frame is
     // given everything it will need to load any accessible subresources. We
     // however only do this for cross-document navigations, because the
     // alternative would be redundant effort.
-    network::mojom::URLLoaderFactoryPtr default_factory;
+    network::mojom::URLLoaderFactoryPtrInfo default_factory_info;
     StoragePartitionImpl* storage_partition =
         static_cast<StoragePartitionImpl*>(BrowserContext::GetStoragePartition(
             GetSiteInstance()->GetBrowserContext(), GetSiteInstance()));
@@ -3528,8 +3529,8 @@
         subresource_loader_params->loader_factory_info.is_valid()) {
       // If the caller has supplied a default URLLoaderFactory override (for
       // e.g. appcache, Service Worker, etc.), use that.
-      default_factory.Bind(
-          std::move(subresource_loader_params->loader_factory_info));
+      default_factory_info =
+          std::move(subresource_loader_params->loader_factory_info);
     } else {
       std::string scheme = common_params.url.scheme();
       const auto& schemes = URLDataManagerBackend::GetWebUISchemes();
@@ -3539,41 +3540,41 @@
         if (enabled_bindings_ & BINDINGS_POLICY_WEB_UI) {
           // If the renderer has webui bindings, then don't give it access to
           // network loader for security reasons.
-          default_factory = std::move(factory_for_webui);
+          default_factory_info = factory_for_webui.PassInterface();
         } else {
           // This is a webui scheme that doesn't have webui bindings. Give it
           // access to the network loader as it might require it.
-          subresource_loader_factories->RegisterFactory(
-              scheme, std::move(factory_for_webui));
+          subresource_loader_factories->factories_info().emplace(
+              scheme, factory_for_webui.PassInterface());
         }
       }
     }
 
-    if (!default_factory.is_bound()) {
+    if (!default_factory_info) {
       // Otherwise default to a Network Service-backed loader from the
       // appropriate NetworkContext.
       if (g_url_loader_factory_callback_for_test.Get().is_null()) {
         storage_partition->GetNetworkContext()->CreateURLLoaderFactory(
-            mojo::MakeRequest(&default_factory), GetProcess()->GetID());
+            mojo::MakeRequest(&default_factory_info), GetProcess()->GetID());
       } else {
         network::mojom::URLLoaderFactoryPtr original_factory;
         storage_partition->GetNetworkContext()->CreateURLLoaderFactory(
             mojo::MakeRequest(&original_factory), GetProcess()->GetID());
         g_url_loader_factory_callback_for_test.Get().Run(
-            mojo::MakeRequest(&default_factory), GetProcess()->GetID(),
+            mojo::MakeRequest(&default_factory_info), GetProcess()->GetID(),
             original_factory.PassInterface());
       }
     }
 
-    DCHECK(default_factory.is_bound());
-    subresource_loader_factories->SetDefaultFactory(std::move(default_factory));
-
+    DCHECK(default_factory_info);
+    subresource_loader_factories->default_factory_info() =
+        std::move(default_factory_info);
     // Everyone gets a blob loader.
-    network::mojom::URLLoaderFactoryPtr blob_factory;
+    network::mojom::URLLoaderFactoryPtrInfo blob_factory_info;
     storage_partition->GetBlobURLLoaderFactory()->HandleRequest(
-        mojo::MakeRequest(&blob_factory));
-    subresource_loader_factories->RegisterFactory(url::kBlobScheme,
-                                                  std::move(blob_factory));
+        mojo::MakeRequest(&blob_factory_info));
+    subresource_loader_factories->factories_info().emplace(
+        url::kBlobScheme, std::move(blob_factory_info));
 
     non_network_url_loader_factories_.clear();
 
@@ -3594,10 +3595,10 @@
             this, common_params.url, &non_network_url_loader_factories_);
 
     for (auto& factory : non_network_url_loader_factories_) {
-      network::mojom::URLLoaderFactoryPtr factory_proxy;
-      factory.second->Clone(mojo::MakeRequest(&factory_proxy));
-      subresource_loader_factories->RegisterFactory(factory.first,
-                                                    std::move(factory_proxy));
+      network::mojom::URLLoaderFactoryPtrInfo factory_proxy_info;
+      factory.second->Clone(mojo::MakeRequest(&factory_proxy_info));
+      subresource_loader_factories->factories_info().emplace(
+          factory.first, std::move(factory_proxy_info));
     }
 
     // Pass the controller service worker info if we have one.
@@ -3611,7 +3612,7 @@
   // subresource ULFs when the Network Service is enabled.
   DCHECK(!base::FeatureList::IsEnabled(features::kNetworkService) ||
          is_same_document || !is_first_navigation ||
-         subresource_loader_factories.has_value());
+         subresource_loader_factories);
 
   GetNavigationControl()->CommitNavigation(
       head, body_url, common_params, request_params,
@@ -3662,22 +3663,23 @@
       static_cast<StoragePartitionImpl*>(BrowserContext::GetStoragePartition(
           GetSiteInstance()->GetBrowserContext(), GetSiteInstance()));
 
-  network::mojom::URLLoaderFactoryPtr default_factory;
+  network::mojom::URLLoaderFactoryPtrInfo default_factory_info;
   if (g_url_loader_factory_callback_for_test.Get().is_null()) {
     storage_partition->GetNetworkContext()->CreateURLLoaderFactory(
-        mojo::MakeRequest(&default_factory), GetProcess()->GetID());
+        mojo::MakeRequest(&default_factory_info), GetProcess()->GetID());
   } else {
     network::mojom::URLLoaderFactoryPtr original_factory;
     storage_partition->GetNetworkContext()->CreateURLLoaderFactory(
         mojo::MakeRequest(&original_factory), GetProcess()->GetID());
     g_url_loader_factory_callback_for_test.Get().Run(
-        mojo::MakeRequest(&default_factory), GetProcess()->GetID(),
+        mojo::MakeRequest(&default_factory_info), GetProcess()->GetID(),
         original_factory.PassInterface());
   }
 
-  base::Optional<URLLoaderFactoryBundle> subresource_loader_factories;
-  subresource_loader_factories.emplace();
-  subresource_loader_factories->SetDefaultFactory(std::move(default_factory));
+  auto subresource_loader_factories =
+      std::make_unique<URLLoaderFactoryBundleInfo>(
+          std::move(default_factory_info),
+          std::map<std::string, network::mojom::URLLoaderFactoryPtrInfo>());
 
   GetNavigationControl()->CommitFailedNavigation(
       common_params, request_params, has_stale_copy_in_cache, error_code,
diff --git a/content/common/url_loader_factory_bundle.cc b/content/common/url_loader_factory_bundle.cc
index af3f4d01..17dd351 100644
--- a/content/common/url_loader_factory_bundle.cc
+++ b/content/common/url_loader_factory_bundle.cc
@@ -4,46 +4,42 @@
 
 #include "content/common/url_loader_factory_bundle.h"
 
-#include <map>
-#include <string>
-
-#include "base/macros.h"
-#include "services/network/public/interfaces/url_loader_factory.mojom.h"
+#include "base/logging.h"
 #include "url/gurl.h"
 
-class GURL;
-
 namespace content {
 
-URLLoaderFactoryBundleInfo::URLLoaderFactoryBundleInfo(
-    URLLoaderFactoryBundleInfo&&) = default;
+URLLoaderFactoryBundleInfo::URLLoaderFactoryBundleInfo() = default;
 
 URLLoaderFactoryBundleInfo::URLLoaderFactoryBundleInfo(
     network::mojom::URLLoaderFactoryPtrInfo default_factory_info,
     std::map<std::string, network::mojom::URLLoaderFactoryPtrInfo>
         factories_info)
-    : default_factory_info(std::move(default_factory_info)),
-      factories_info(std::move(factories_info)) {}
+    : default_factory_info_(std::move(default_factory_info)),
+      factories_info_(std::move(factories_info)) {}
 
 URLLoaderFactoryBundleInfo::~URLLoaderFactoryBundleInfo() = default;
 
+scoped_refptr<SharedURLLoaderFactory>
+URLLoaderFactoryBundleInfo::CreateFactory() {
+  auto other = std::make_unique<URLLoaderFactoryBundleInfo>();
+  other->default_factory_info_ = std::move(default_factory_info_);
+  other->factories_info_ = std::move(factories_info_);
+
+  return base::MakeRefCounted<URLLoaderFactoryBundle>(std::move(other));
+}
+
 URLLoaderFactoryBundle::URLLoaderFactoryBundle() = default;
 
-URLLoaderFactoryBundle::URLLoaderFactoryBundle(URLLoaderFactoryBundle&&) =
-    default;
-
 URLLoaderFactoryBundle::URLLoaderFactoryBundle(
-    URLLoaderFactoryBundleInfo info) {
-  default_factory_.Bind(std::move(info.default_factory_info));
-  for (auto& factory_info : info.factories_info)
+    std::unique_ptr<URLLoaderFactoryBundleInfo> info) {
+  default_factory_.Bind(std::move(info->default_factory_info()));
+  for (auto& factory_info : info->factories_info())
     factories_[factory_info.first].Bind(std::move(factory_info.second));
 }
 
 URLLoaderFactoryBundle::~URLLoaderFactoryBundle() = default;
 
-URLLoaderFactoryBundle& URLLoaderFactoryBundle::operator=(
-    URLLoaderFactoryBundle&&) = default;
-
 void URLLoaderFactoryBundle::SetDefaultFactory(
     network::mojom::URLLoaderFactoryPtr factory) {
   default_factory_ = std::move(factory);
@@ -67,29 +63,38 @@
   return it->second.get();
 }
 
-URLLoaderFactoryBundleInfo URLLoaderFactoryBundle::PassInfo() {
-  std::map<std::string, network::mojom::URLLoaderFactoryPtrInfo> factories_info;
-  for (auto& factory : factories_)
-    factories_info.emplace(factory.first, factory.second.PassInterface());
-  DCHECK(default_factory_.is_bound());
-  return URLLoaderFactoryBundleInfo(default_factory_.PassInterface(),
-                                    std::move(factories_info));
+void URLLoaderFactoryBundle::CreateLoaderAndStart(
+    network::mojom::URLLoaderRequest loader,
+    int32_t routing_id,
+    int32_t request_id,
+    uint32_t options,
+    const network::ResourceRequest& request,
+    network::mojom::URLLoaderClientPtr client,
+    const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
+    const Constraints& constaints) {
+  network::mojom::URLLoaderFactory* factory_ptr =
+      GetFactoryForRequest(request.url);
+
+  factory_ptr->CreateLoaderAndStart(std::move(loader), routing_id, request_id,
+                                    options, request, std::move(client),
+                                    traffic_annotation);
 }
 
-URLLoaderFactoryBundle URLLoaderFactoryBundle::Clone() {
-  DCHECK(default_factory_.is_bound());
-  network::mojom::URLLoaderFactoryPtr cloned_default_factory;
-  default_factory_->Clone(mojo::MakeRequest(&cloned_default_factory));
+std::unique_ptr<SharedURLLoaderFactoryInfo> URLLoaderFactoryBundle::Clone() {
+  DCHECK(default_factory_);
 
-  URLLoaderFactoryBundle new_bundle;
-  new_bundle.SetDefaultFactory(std::move(cloned_default_factory));
+  network::mojom::URLLoaderFactoryPtrInfo default_factory_info;
+  default_factory_->Clone(mojo::MakeRequest(&default_factory_info));
+
+  std::map<std::string, network::mojom::URLLoaderFactoryPtrInfo> factories_info;
   for (auto& factory : factories_) {
-    network::mojom::URLLoaderFactoryPtr cloned_factory;
-    factory.second->Clone(mojo::MakeRequest(&cloned_factory));
-    new_bundle.RegisterFactory(factory.first, std::move(cloned_factory));
+    network::mojom::URLLoaderFactoryPtrInfo factory_info;
+    factory.second->Clone(mojo::MakeRequest(&factory_info));
+    factories_info.emplace(factory.first, std::move(factory_info));
   }
 
-  return new_bundle;
+  return std::make_unique<URLLoaderFactoryBundleInfo>(
+      std::move(default_factory_info), std::move(factories_info));
 }
 
 }  // namespace content
diff --git a/content/common/url_loader_factory_bundle.h b/content/common/url_loader_factory_bundle.h
index 3c18c3c..5a6c4a9 100644
--- a/content/common/url_loader_factory_bundle.h
+++ b/content/common/url_loader_factory_bundle.h
@@ -10,44 +10,53 @@
 
 #include "base/macros.h"
 #include "content/common/content_export.h"
+#include "content/public/common/shared_url_loader_factory.h"
 #include "services/network/public/interfaces/url_loader_factory.mojom.h"
 
 class GURL;
 
-namespace mojo {
-template <typename, typename>
-struct StructTraits;
-}
-
 namespace content {
-namespace mojom {
-class URLLoaderFactoryBundleDataView;
-}
 
 // Holds the internal state of a URLLoaderFactoryBundle in a form that is safe
 // to pass across sequences.
-struct CONTENT_EXPORT URLLoaderFactoryBundleInfo {
-  URLLoaderFactoryBundleInfo(URLLoaderFactoryBundleInfo&&);
+class CONTENT_EXPORT URLLoaderFactoryBundleInfo
+    : public SharedURLLoaderFactoryInfo {
+ public:
+  URLLoaderFactoryBundleInfo();
   URLLoaderFactoryBundleInfo(
       network::mojom::URLLoaderFactoryPtrInfo default_factory_info,
       std::map<std::string, network::mojom::URLLoaderFactoryPtrInfo>
           factories_info);
-  ~URLLoaderFactoryBundleInfo();
+  ~URLLoaderFactoryBundleInfo() override;
 
-  network::mojom::URLLoaderFactoryPtrInfo default_factory_info;
-  std::map<std::string, network::mojom::URLLoaderFactoryPtrInfo> factories_info;
+  network::mojom::URLLoaderFactoryPtrInfo& default_factory_info() {
+    return default_factory_info_;
+  }
+
+  std::map<std::string, network::mojom::URLLoaderFactoryPtrInfo>&
+  factories_info() {
+    return factories_info_;
+  }
+
+ private:
+  // SharedURLLoaderFactoryInfo implementation.
+  scoped_refptr<SharedURLLoaderFactory> CreateFactory() override;
+
+  network::mojom::URLLoaderFactoryPtrInfo default_factory_info_;
+  std::map<std::string, network::mojom::URLLoaderFactoryPtrInfo>
+      factories_info_;
+
+  DISALLOW_COPY_AND_ASSIGN(URLLoaderFactoryBundleInfo);
 };
 
 // Encapsulates a collection of URLLoaderFactoryPtrs which can be usd to acquire
 // loaders for various types of resource requests.
-class CONTENT_EXPORT URLLoaderFactoryBundle {
+class CONTENT_EXPORT URLLoaderFactoryBundle : public SharedURLLoaderFactory {
  public:
   URLLoaderFactoryBundle();
-  URLLoaderFactoryBundle(URLLoaderFactoryBundle&&);
-  explicit URLLoaderFactoryBundle(URLLoaderFactoryBundleInfo info);
-  ~URLLoaderFactoryBundle();
 
-  URLLoaderFactoryBundle& operator=(URLLoaderFactoryBundle&&);
+  explicit URLLoaderFactoryBundle(
+      std::unique_ptr<URLLoaderFactoryBundleInfo> info);
 
   // Sets the default factory to use when no registered factories match a given
   // |url|.
@@ -62,25 +71,24 @@
   // is undefined behavior to call this when no default factory is set.
   network::mojom::URLLoaderFactory* GetFactoryForRequest(const GURL& url);
 
-  // Passes out a structure which captures the internal state of this bundle in
-  // a form that is safe to pass across sequences. Effectively resets |this|
-  // to have no registered factories.
-  URLLoaderFactoryBundleInfo PassInfo();
+  // SharedURLLoaderFactory implementation.
+  void CreateLoaderAndStart(
+      network::mojom::URLLoaderRequest loader,
+      int32_t routing_id,
+      int32_t request_id,
+      uint32_t options,
+      const network::ResourceRequest& request,
+      network::mojom::URLLoaderClientPtr client,
+      const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
+      const Constraints& constaints = kDefaultConstraints) override;
 
-  // Creates a clone of this bundle which can be passed to and owned by another
-  // consumer. The clone operates identically to but independent from the
-  // original (this) bundle.
-  URLLoaderFactoryBundle Clone();
+  std::unique_ptr<SharedURLLoaderFactoryInfo> Clone() override;
 
  private:
-  friend struct mojo::StructTraits<
-      content::mojom::URLLoaderFactoryBundleDataView,
-      URLLoaderFactoryBundle>;
+  ~URLLoaderFactoryBundle() override;
 
   network::mojom::URLLoaderFactoryPtr default_factory_;
   std::map<std::string, network::mojom::URLLoaderFactoryPtr> factories_;
-
-  DISALLOW_COPY_AND_ASSIGN(URLLoaderFactoryBundle);
 };
 
 }  // namespace content
diff --git a/content/common/url_loader_factory_bundle.typemap b/content/common/url_loader_factory_bundle.typemap
index 066c04c..1689e50 100644
--- a/content/common/url_loader_factory_bundle.typemap
+++ b/content/common/url_loader_factory_bundle.typemap
@@ -10,4 +10,4 @@
   "//content/common/url_loader_factory_bundle_struct_traits.cc",
 ]
 
-type_mappings = [ "content.mojom.URLLoaderFactoryBundle=content::URLLoaderFactoryBundle[move_only]" ]
+type_mappings = [ "content.mojom.URLLoaderFactoryBundle=std::unique_ptr<content::URLLoaderFactoryBundleInfo>[move_only,nullable_is_same_type]" ]
diff --git a/content/common/url_loader_factory_bundle_struct_traits.cc b/content/common/url_loader_factory_bundle_struct_traits.cc
index 0c84988..e0627fb 100644
--- a/content/common/url_loader_factory_bundle_struct_traits.cc
+++ b/content/common/url_loader_factory_bundle_struct_traits.cc
@@ -6,28 +6,32 @@
 
 namespace mojo {
 
-using Traits = StructTraits<content::mojom::URLLoaderFactoryBundleDataView,
-                            content::URLLoaderFactoryBundle>;
+using Traits =
+    StructTraits<content::mojom::URLLoaderFactoryBundleDataView,
+                 std::unique_ptr<content::URLLoaderFactoryBundleInfo>>;
 
 // static
-network::mojom::URLLoaderFactoryPtr Traits::default_factory(
-    content::URLLoaderFactoryBundle& bundle) {
-  return std::move(bundle.default_factory_);
+network::mojom::URLLoaderFactoryPtrInfo Traits::default_factory(
+    BundleInfoType& bundle) {
+  return std::move(bundle->default_factory_info());
 }
 
 // static
-std::map<std::string, network::mojom::URLLoaderFactoryPtr> Traits::factories(
-    content::URLLoaderFactoryBundle& bundle) {
-  return std::move(bundle.factories_);
+std::map<std::string, network::mojom::URLLoaderFactoryPtrInfo>
+Traits::factories(BundleInfoType& bundle) {
+  return std::move(bundle->factories_info());
 }
 
 // static
 bool Traits::Read(content::mojom::URLLoaderFactoryBundleDataView data,
-                  content::URLLoaderFactoryBundle* out_bundle) {
-  out_bundle->SetDefaultFactory(
-      data.TakeDefaultFactory<network::mojom::URLLoaderFactoryPtr>());
-  if (!data.ReadFactories(&out_bundle->factories_))
+                  BundleInfoType* out_bundle) {
+  *out_bundle = std::make_unique<content::URLLoaderFactoryBundleInfo>();
+
+  (*out_bundle)->default_factory_info() =
+      data.TakeDefaultFactory<network::mojom::URLLoaderFactoryPtrInfo>();
+  if (!data.ReadFactories(&(*out_bundle)->factories_info()))
     return false;
+
   return true;
 }
 
diff --git a/content/common/url_loader_factory_bundle_struct_traits.h b/content/common/url_loader_factory_bundle_struct_traits.h
index 772e637..e8d9220 100644
--- a/content/common/url_loader_factory_bundle_struct_traits.h
+++ b/content/common/url_loader_factory_bundle_struct_traits.h
@@ -13,15 +13,21 @@
 
 template <>
 struct StructTraits<content::mojom::URLLoaderFactoryBundleDataView,
-                    content::URLLoaderFactoryBundle> {
-  static network::mojom::URLLoaderFactoryPtr default_factory(
-      content::URLLoaderFactoryBundle& bundle);
+                    std::unique_ptr<content::URLLoaderFactoryBundleInfo>> {
+  using BundleInfoType = std::unique_ptr<content::URLLoaderFactoryBundleInfo>;
 
-  static std::map<std::string, network::mojom::URLLoaderFactoryPtr> factories(
-      content::URLLoaderFactoryBundle& bundle);
+  static bool IsNull(const BundleInfoType& bundle) { return !bundle; }
+
+  static void SetToNull(BundleInfoType* bundle) { bundle->reset(); }
+
+  static network::mojom::URLLoaderFactoryPtrInfo default_factory(
+      BundleInfoType& bundle);
+
+  static std::map<std::string, network::mojom::URLLoaderFactoryPtrInfo>
+  factories(BundleInfoType& bundle);
 
   static bool Read(content::mojom::URLLoaderFactoryBundleDataView data,
-                   content::URLLoaderFactoryBundle* out_bundle);
+                   BundleInfoType* out_bundle);
 };
 
 }  // namespace mojo
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 4bbed39f..78f7d40 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -776,14 +776,12 @@
     DCHECK(frame_);
     frame_->UpdatePeakMemoryStats();
 
-    // TODO(crbug.com/796425): Temporarily wrap the raw mojom::URLLoaderFactory
-    // pointer into SharedURLLoaderFactory.
     scoped_refptr<SharedURLLoaderFactory> factory;
     if (base::FeatureList::IsEnabled(features::kNetworkService)) {
-      factory = base::MakeRefCounted<WeakWrapperSharedURLLoaderFactory>(
-          frame_->GetSubresourceLoaderFactories().GetFactoryForRequest(
-              request.Url()));
+      factory = frame_->GetSubresourceLoaderFactories();
     } else {
+      // TODO(crbug.com/796425): Temporarily wrap the raw
+      // mojom::URLLoaderFactory pointer into SharedURLLoaderFactory.
       factory = base::MakeRefCounted<WeakWrapperSharedURLLoaderFactory>(
           frame_->GetDefaultURLLoaderFactoryGetter()->GetFactoryForURL(
               request.Url(), frame_->custom_url_loader_factory()));
@@ -3071,7 +3069,7 @@
     const CommonNavigationParams& common_params,
     const RequestNavigationParams& request_params,
     network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
-    base::Optional<URLLoaderFactoryBundle> subresource_loader_factories,
+    std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories,
     mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info,
     const base::UnguessableToken& devtools_navigation_token) {
   // If this was a renderer-initiated navigation (nav_entry_id == 0) from this
@@ -3164,16 +3162,19 @@
   DCHECK(is_same_document ||
          common_params.url.SchemeIs(url::kJavaScriptScheme) ||
          !base::FeatureList::IsEnabled(features::kNetworkService) ||
-         subresource_loader_factories.has_value());
+         subresource_loader_factories);
 
-  if (subresource_loader_factories)
-    subresource_loader_factories_ = std::move(subresource_loader_factories);
+  if (subresource_loader_factories) {
+    subresource_loader_factories_ =
+        base::MakeRefCounted<URLLoaderFactoryBundle>(
+            std::move(subresource_loader_factories));
+  }
 
   // If the Network Service is enabled, by this point the frame should always
   // have subresource loader factories, even if they're from a previous (but
   // same-document) commit.
   DCHECK(!base::FeatureList::IsEnabled(features::kNetworkService) ||
-         subresource_loader_factories_.has_value());
+         subresource_loader_factories_);
 
   // Used to determine whether this frame is actually loading a request as part
   // of a history navigation.
@@ -3321,7 +3322,7 @@
     bool has_stale_copy_in_cache,
     int error_code,
     const base::Optional<std::string>& error_page_content,
-    base::Optional<URLLoaderFactoryBundle> subresource_loader_factories) {
+    std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories) {
   bool is_reload =
       FrameMsg_Navigate_Type::IsReload(common_params.navigation_type);
   RenderFrameImpl::PrepareRenderViewForNavigation(common_params.url,
@@ -3330,8 +3331,11 @@
   GetContentClient()->SetActiveURL(
       common_params.url, frame_->Top()->GetSecurityOrigin().ToString().Utf8());
 
-  if (subresource_loader_factories)
-    subresource_loader_factories_ = std::move(subresource_loader_factories);
+  if (subresource_loader_factories) {
+    subresource_loader_factories_ =
+        base::MakeRefCounted<URLLoaderFactoryBundle>(
+            std::move(subresource_loader_factories));
+  }
 
   pending_navigation_params_.reset(
       new NavigationParams(common_params, request_params));
@@ -6508,16 +6512,19 @@
   return request;
 }
 
-URLLoaderFactoryBundle& RenderFrameImpl::GetSubresourceLoaderFactories() {
+URLLoaderFactoryBundle* RenderFrameImpl::GetSubresourceLoaderFactories() {
   DCHECK(base::FeatureList::IsEnabled(features::kNetworkService));
   if (!subresource_loader_factories_) {
     RenderFrameImpl* creator = RenderFrameImpl::FromWebFrame(
         frame_->Parent() ? frame_->Parent() : frame_->Opener());
     DCHECK(creator);
+    auto bundle_info =
+        base::WrapUnique(static_cast<URLLoaderFactoryBundleInfo*>(
+            creator->GetSubresourceLoaderFactories()->Clone().release()));
     subresource_loader_factories_ =
-        creator->GetSubresourceLoaderFactories().Clone();
+        base::MakeRefCounted<URLLoaderFactoryBundle>(std::move(bundle_info));
   }
-  return *subresource_loader_factories_;
+  return subresource_loader_factories_.get();
 }
 
 void RenderFrameImpl::UpdateEncoding(WebFrame* frame,
@@ -6592,7 +6599,7 @@
     // When the network service is enabled, all subresource loads go through
     // a factory from |subresource_loader_factories|. In this case we simply
     // replace the existing default factory within the bundle.
-    GetSubresourceLoaderFactories().SetDefaultFactory(std::move(factory));
+    GetSubresourceLoaderFactories()->SetDefaultFactory(std::move(factory));
   } else {
     custom_url_loader_factory_ = std::move(factory);
   }
@@ -7114,7 +7121,7 @@
 network::mojom::URLLoaderFactory* RenderFrameImpl::GetURLLoaderFactory(
     const GURL& request_url) {
   if (base::FeatureList::IsEnabled(features::kNetworkService)) {
-    return GetSubresourceLoaderFactories().GetFactoryForRequest(request_url);
+    return GetSubresourceLoaderFactories()->GetFactoryForRequest(request_url);
   }
 
   return GetDefaultURLLoaderFactoryGetter()->GetFactoryForURL(request_url);
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 721c0d5b..7097b46 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -527,7 +527,7 @@
       const CommonNavigationParams& common_params,
       const RequestNavigationParams& request_params,
       network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
-      base::Optional<URLLoaderFactoryBundle> subresource_loaders,
+      std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders,
       mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info,
       const base::UnguessableToken& devtools_navigation_token) override;
   void CommitFailedNavigation(
@@ -536,7 +536,7 @@
       bool has_stale_copy_in_cache,
       int error_code,
       const base::Optional<std::string>& error_page_content,
-      base::Optional<URLLoaderFactoryBundle> subresource_loaders) override;
+      std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders) override;
 
   // mojom::FullscreenVideoElementHandler implementation:
   void RequestFullscreenVideoElement() override;
@@ -1116,7 +1116,7 @@
   // browser at navigation time. For any other frames (i.e. frames on the
   // initial about:blank Document), the bundle returned here is lazily cloned
   // from the parent or opener's own bundle.
-  URLLoaderFactoryBundle& GetSubresourceLoaderFactories();
+  URLLoaderFactoryBundle* GetSubresourceLoaderFactories();
 
   // Update current main frame's encoding and send it to browser window.
   // Since we want to let users see the right encoding info from menu
@@ -1607,7 +1607,7 @@
 
   // URLLoaderFactory instances used for subresource loading when the Network
   // Service is enabled.
-  base::Optional<URLLoaderFactoryBundle> subresource_loader_factories_;
+  scoped_refptr<URLLoaderFactoryBundle> subresource_loader_factories_;
 
   // AndroidOverlay routing token from the browser, if we have one yet.
   base::Optional<base::UnguessableToken> overlay_routing_token_;
diff --git a/content/test/test_render_frame.cc b/content/test/test_render_frame.cc
index 9e07a73..a82c6cb6 100644
--- a/content/test/test_render_frame.cc
+++ b/content/test/test_render_frame.cc
@@ -140,11 +140,12 @@
 
 void TestRenderFrame::Navigate(const CommonNavigationParams& common_params,
                                const RequestNavigationParams& request_params) {
-  CommitNavigation(
-      network::ResourceResponseHead(), GURL(), common_params, request_params,
-      network::mojom::URLLoaderClientEndpointsPtr(), URLLoaderFactoryBundle(),
-      mojom::ControllerServiceWorkerInfoPtr(),
-      base::UnguessableToken::Create());
+  CommitNavigation(network::ResourceResponseHead(), GURL(), common_params,
+                   request_params,
+                   network::mojom::URLLoaderClientEndpointsPtr(),
+                   std::make_unique<URLLoaderFactoryBundleInfo>(),
+                   mojom::ControllerServiceWorkerInfoPtr(),
+                   base::UnguessableToken::Create());
 }
 
 void TestRenderFrame::SwapOut(
diff --git a/content/test/test_render_frame_host.cc b/content/test/test_render_frame_host.cc
index 5d7ce5e2..52e8670 100644
--- a/content/test/test_render_frame_host.cc
+++ b/content/test/test_render_frame_host.cc
@@ -64,7 +64,7 @@
       const CommonNavigationParams& common_params,
       const RequestNavigationParams& request_params,
       network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
-      base::Optional<URLLoaderFactoryBundle> subresource_loader_factories,
+      std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories,
       mojom::ControllerServiceWorkerInfoPtr controller_service_worker,
       const base::UnguessableToken& devtools_navigation_token) override {
     frame_host_->GetProcess()->set_did_frame_commit_navigation(true);
@@ -81,8 +81,8 @@
       bool has_stale_copy_in_cache,
       int32_t error_code,
       const base::Optional<std::string>& error_page_content,
-      base::Optional<content::URLLoaderFactoryBundle>
-          subresource_loader_factories) override {}
+      std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories)
+      override {}
 
  private:
   TestRenderFrameHost* const frame_host_;