Reland "Reland "Consolidate iframe & object resource timing code paths""

This reverts commit d1b49ff4d15bc538c4feddff9f81253bba6abd9d.

Reason for revert: The failing tests will be fixed instead of reverting the original CL that caused them.

Original change's description:
> Revert "Reland "Consolidate iframe & object resource timing code paths""
>
> This reverts commit c8d82e52681f338bc4671df333a2bc9d6c93a32c.
>
> Reason for revert: Unblocking revert at https://crrev.com/c/4295184
>
> Original change's description:
> > Reland "Consolidate iframe & object resource timing code paths"
> >
> > This is a reland of commit 5dcb6f7b01d5f51144a9ba847c34bb0cdc344ccb
> >
> > (Reland change: initializing
> > WebNavigationTimings::parent_resource_timing_access, caught by MSAN)
> > Original change's description:
> > > Consolidate iframe & object resource timing code paths
> > >
> > > So far some of the logic  in resource timing for subframe navigations
> > > iframe/object/embed) was duplicated, e.g. both in blink and in content.
> > >
> > > This has led to race conditions, inconsistencies and sometimes
> > > XSS leaks.
> > >
> > > This patch attempts to improve the situation by consolidating the code
> > > paths:
> > >
> > > - NavigationRequest receives is_container_initiated, which ensures only
> > >   container-initiated navigations are reported to the parent. This
> > >   is a clarification of something that was ambiguous in the spec
> > >   previously (https://github.com/whatwg/html/issues/8846).
> > >   It later uses ParentResourceTimingAccess to decide if a navigation
> > >   should report to its parent with/without response details
> > >   (status code and mime-type), or not report at all (TAO-fail, not
> > >   an iframe, not container-initiated).
> > >
> > > - Both object fallbacks and cancelled navigations (204/205) report
> > >   to the parent via RenderFrameImpl, and blink converts that to a
> > >   ResourceTimingInfo object. This allows us to remove the duplicated
> > >   resource timing creation code in //content.
> > >
> > > - We report fallback resource timing also for plugin error events and
> > >   not only for load events.
> > >
> > > Bug: 1399862
> > > Bug: 1410705
> > > Change-Id: Id37d23cd02eee9e38f812e6f3da99caedafdee3d
> > > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4214695
> > > Reviewed-by: Takashi Toyoshima <[email protected]>
> > > Reviewed-by: Daniel Cheng <[email protected]>
> > > Reviewed-by: Arthur Sonzogni <[email protected]>
> > > Commit-Queue: Noam Rosenthal <[email protected]>
> > > Cr-Commit-Position: refs/heads/main@{#1110433}
> >
> > Bug: 1399862
> > Bug: 1410705
> > Change-Id: Ica01bcc861ffd60909e9adad79ef2f71ab23f98e
> > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4296794
> > Reviewed-by: Arthur Sonzogni <[email protected]>
> > Reviewed-by: Takashi Toyoshima <[email protected]>
> > Commit-Queue: Noam Rosenthal <[email protected]>
> > Reviewed-by: Yoav Weiss <[email protected]>
> > Reviewed-by: Daniel Cheng <[email protected]>
> > Cr-Commit-Position: refs/heads/main@{#1110858}
>
> Bug: 1399862
> Bug: 1410705
> Change-Id: I35e3a03d38be4d2cc42d18ee0ed0296b978da090
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4299069
> Auto-Submit: Sergey Poromov <[email protected]>
> Reviewed-by: Sergey Poromov <[email protected]>
> Owners-Override: Sergey Poromov <[email protected]>
> Bot-Commit: Rubber Stamper <[email protected]>
> Commit-Queue: Sergey Poromov <[email protected]>
> Cr-Commit-Position: refs/heads/main@{#1111499}

Bug: 1399862
Bug: 1410705
Change-Id: I3458949b0632b266e24a000a10f864189fd8d1db
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4299070
Auto-Submit: Sergey Poromov <[email protected]>
Owners-Override: Sergey Poromov <[email protected]>
Bot-Commit: Rubber Stamper <[email protected]>
Commit-Queue: Rubber Stamper <[email protected]>
Commit-Queue: Sergey Poromov <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1111522}
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 595bb3f..817f608 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -1197,8 +1197,6 @@
     "loader/prefetch_url_loader.h",
     "loader/prefetch_url_loader_service.cc",
     "loader/prefetch_url_loader_service.h",
-    "loader/resource_timing_utils.cc",
-    "loader/resource_timing_utils.h",
     "loader/shared_cors_origin_access_list_impl.cc",
     "loader/shared_cors_origin_access_list_impl.h",
     "loader/url_loader_throttles.cc",
diff --git a/content/browser/loader/navigation_url_loader_impl_unittest.cc b/content/browser/loader/navigation_url_loader_impl_unittest.cc
index 43df28f..35521b4 100644
--- a/content/browser/loader/navigation_url_loader_impl_unittest.cc
+++ b/content/browser/loader/navigation_url_loader_impl_unittest.cc
@@ -237,7 +237,8 @@
             base::TimeTicks() /* renderer_before_unload_end */,
             absl::nullopt /* web_bundle_token */,
             blink::mojom::NavigationInitiatorActivationAndAdStatus::
-                kDidNotStartWithTransientActivation);
+                kDidNotStartWithTransientActivation,
+            false /* is_container_initiated */);
 
     auto common_params = blink::CreateCommonNavigationParams();
     common_params->url = url;
diff --git a/content/browser/loader/navigation_url_loader_unittest.cc b/content/browser/loader/navigation_url_loader_unittest.cc
index 3df6640..229b08c 100644
--- a/content/browser/loader/navigation_url_loader_unittest.cc
+++ b/content/browser/loader/navigation_url_loader_unittest.cc
@@ -98,7 +98,8 @@
             base::TimeTicks() /* renderer_before_unload_end */,
             absl::nullopt /* web_bundle_token */,
             blink::mojom::NavigationInitiatorActivationAndAdStatus::
-                kDidNotStartWithTransientActivation);
+                kDidNotStartWithTransientActivation,
+            false /* is_container_initiated */);
     auto common_params = blink::CreateCommonNavigationParams();
     common_params->url = url;
     common_params->initiator_origin = url::Origin::Create(url);
diff --git a/content/browser/loader/object_navigation_fallback_body_loader.cc b/content/browser/loader/object_navigation_fallback_body_loader.cc
index f7b0f41..57405999 100644
--- a/content/browser/loader/object_navigation_fallback_body_loader.cc
+++ b/content/browser/loader/object_navigation_fallback_body_loader.cc
@@ -10,7 +10,6 @@
 #include "base/containers/contains.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback_helpers.h"
-#include "content/browser/loader/resource_timing_utils.h"
 #include "content/browser/renderer_host/frame_tree_node.h"
 #include "content/browser/renderer_host/navigation_request.h"
 #include "content/browser/renderer_host/render_frame_host_impl.h"
@@ -32,35 +31,15 @@
 
 namespace content {
 
-namespace {
-
-std::string ExtractServerTimingValueIfNeeded(
-    const network::mojom::URLResponseHead& response_head) {
-  std::string value;
-  if (!response_head.timing_allow_passed)
-    return value;
-
-  // Note: the renderer will be responsible for parsing the actual server
-  // timing values.
-  response_head.headers->GetNormalizedHeader("Server-Timing", &value);
-  return value;
-}
-
-}  // namespace
-
 NAVIGATION_HANDLE_USER_DATA_KEY_IMPL(ObjectNavigationFallbackBodyLoader);
 
 // static
 void ObjectNavigationFallbackBodyLoader::CreateAndStart(
     NavigationRequest& navigation_request,
-    const blink::mojom::CommonNavigationParams& common_params,
-    const blink::mojom::CommitNavigationParams& commit_params,
-    const network::mojom::URLResponseHead& response_head,
     mojo::ScopedDataPipeConsumerHandle response_body,
     network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
     base::OnceClosure completion_closure) {
   // This should only be called for HTTP errors.
-  DCHECK(response_head.headers);
   RenderFrameHostImpl* render_frame_host =
       navigation_request.frame_tree_node()->current_frame_host();
   // A frame owned by <object> should always have a parent.
@@ -68,25 +47,15 @@
   // It's safe to snapshot the parent origin in the calculation here; if the
   // parent frame navigates, `render_frame_host_` will be deleted, which
   // triggers deletion of `this`, cancelling all remaining work.
-  blink::mojom::ResourceTimingInfoPtr timing_info =
-      GenerateResourceTimingForNavigation(
-          render_frame_host->GetParent()->GetLastCommittedOrigin(),
-          common_params, commit_params, response_head);
-  std::string server_timing_value =
-      ExtractServerTimingValueIfNeeded(response_head);
-
-  CreateForNavigationHandle(
-      navigation_request, std::move(timing_info),
-      std::move(server_timing_value), std::move(response_body),
-      std::move(url_loader_client_endpoints), std::move(completion_closure));
+  CreateForNavigationHandle(navigation_request, std::move(response_body),
+                            std::move(url_loader_client_endpoints),
+                            std::move(completion_closure));
 }
 
 ObjectNavigationFallbackBodyLoader::~ObjectNavigationFallbackBodyLoader() {}
 
 ObjectNavigationFallbackBodyLoader::ObjectNavigationFallbackBodyLoader(
     NavigationHandle& navigation_handle,
-    blink::mojom::ResourceTimingInfoPtr timing_info,
-    std::string server_timing_value,
     mojo::ScopedDataPipeConsumerHandle response_body,
     network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
     base::OnceClosure completion_closure)
@@ -98,8 +67,6 @@
       response_body_drainer_(
           std::make_unique<mojo::DataPipeDrainer>(this,
                                                   std::move(response_body))),
-      timing_info_(std::move(timing_info)),
-      server_timing_value_(std::move(server_timing_value)),
       completion_closure_(std::move(completion_closure)) {
   // Unretained is safe; `url_loader_` is owned by `this` and will not dispatch
   // callbacks after it is destroyed.
@@ -165,25 +132,9 @@
   // `completion_closure_` will delete the NavigationRequest, which will delete
   // `this`.
   base::ScopedClosureRunner cleanup(std::move(completion_closure_));
-
-  timing_info_->response_end = status.completion_time;
-  timing_info_->encoded_body_size = status.encoded_body_length;
-  timing_info_->decoded_body_size = status.decoded_body_length;
-
-  RenderFrameHostManager* render_manager =
-      navigation_request_->frame_tree_node()->render_manager();
-  if (RenderFrameProxyHost* proxy = render_manager->GetProxyToParent()) {
-    if (proxy->is_render_frame_proxy_live()) {
-      proxy->GetAssociatedRemoteFrame()
-          ->RenderFallbackContentWithResourceTiming(std::move(timing_info_),
-                                                    server_timing_value_);
-    }
-  } else {
-    render_manager->current_frame_host()
-        ->GetAssociatedLocalFrame()
-        ->RenderFallbackContentWithResourceTiming(std::move(timing_info_),
-                                                  server_timing_value_);
-  }
+  navigation_request_->AddResourceTimingEntryForFailedSubframeNavigation(
+      status);
+  navigation_request_->RenderFallbackContentForObjectTag();
 }
 
 void ObjectNavigationFallbackBodyLoader::OnDataAvailable(const void* data,
diff --git a/content/browser/loader/object_navigation_fallback_body_loader.h b/content/browser/loader/object_navigation_fallback_body_loader.h
index 34acb77..5568126 100644
--- a/content/browser/loader/object_navigation_fallback_body_loader.h
+++ b/content/browser/loader/object_navigation_fallback_body_loader.h
@@ -21,12 +21,6 @@
 #include "third_party/blink/public/mojom/navigation/navigation_params.mojom-forward.h"
 #include "third_party/blink/public/mojom/timing/resource_timing.mojom.h"
 
-namespace network {
-namespace mojom {
-class URLResponseHead;
-}  // namespace mojom
-}  // namespace network
-
 namespace content {
 
 class NavigationRequest;
@@ -59,9 +53,6 @@
       public network::mojom::URLLoaderClient,
       public mojo::DataPipeDrainer::Client {
  public:
-  // `common_params, `commit_params`, and `response_head`  are used to
-  // (partially) generate the resource timing info.
-  //
   // `response_body` and `url_loader_client_endpoints` are used to drain the
   // responise body and calculate the body / data size needed for the
   // performance entry.
@@ -75,9 +66,6 @@
   // response body is successfully loaded.
   static void CreateAndStart(
       NavigationRequest& navigation_request,
-      const blink::mojom::CommonNavigationParams& common_params,
-      const blink::mojom::CommitNavigationParams& commit_params,
-      const network::mojom::URLResponseHead& response_head,
       mojo::ScopedDataPipeConsumerHandle response_body,
       network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
       base::OnceClosure completion_closure);
@@ -90,8 +78,6 @@
 
   ObjectNavigationFallbackBodyLoader(
       NavigationHandle& navigation_handle,
-      blink::mojom::ResourceTimingInfoPtr timing_info,
-      std::string server_timing_value,
       mojo::ScopedDataPipeConsumerHandle response_body,
       network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
       base::OnceClosure completion_closure);
@@ -123,8 +109,6 @@
   // `response_body_drainer_` will be reset to null when the response body is
   // completely drained.
   std::unique_ptr<mojo::DataPipeDrainer> response_body_drainer_;
-  blink::mojom::ResourceTimingInfoPtr timing_info_;
-  std::string server_timing_value_;
   base::OnceClosure completion_closure_;
 };
 
diff --git a/content/browser/loader/resource_timing_utils.cc b/content/browser/loader/resource_timing_utils.cc
deleted file mode 100644
index 749756ba9a..0000000
--- a/content/browser/loader/resource_timing_utils.cc
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/loader/resource_timing_utils.h"
-
-#include <string>
-#include <utility>
-
-#include "base/containers/contains.h"
-#include "net/http/http_response_info.h"
-#include "third_party/blink/public/mojom/navigation/navigation_params.mojom.h"
-#include "third_party/blink/public/mojom/timing/resource_timing.mojom.h"
-#include "url/gurl.h"
-#include "url/url_util.h"
-
-namespace {
-
-// Implements the TimingAllowOrigin check
-// This logic is duplicated from Performance::AllowsTimingRedirect(). Ensure
-// that any changes are synced between both copies.
-bool IsCrossOriginResponseOrHasCrossOriginRedirects(
-    const url::Origin& parent_origin,
-    const blink::mojom::CommonNavigationParams& common_params,
-    const blink::mojom::CommitNavigationParams& commit_params) {
-  DCHECK_EQ(commit_params.redirect_infos.size(),
-            commit_params.redirect_response.size());
-  for (const auto& info : commit_params.redirect_infos) {
-    if (!parent_origin.IsSameOriginWith(info.new_url)) {
-      return true;
-    }
-  }
-
-  return !parent_origin.IsSameOriginWith(common_params.url);
-}
-
-}  // namespace
-
-namespace content {
-
-// This logic is duplicated from blink::CreateResourceTimingInfo(). Ensure
-// that any changes are synced between both copies.
-blink::mojom::ResourceTimingInfoPtr GenerateResourceTimingForNavigation(
-    const url::Origin& parent_origin,
-    const blink::mojom::CommonNavigationParams& common_params,
-    const blink::mojom::CommitNavigationParams& commit_params,
-    const network::mojom::URLResponseHead& response_head) {
-  // TODO(dcheng): There should be a Blink helper for populating the timing info
-  // that's exposed in //third_party/blink/common. This would allow a lot of the
-  // boilerplate to be shared.
-
-  auto timing_info = blink::mojom::ResourceTimingInfo::New();
-  const GURL& initial_url = !commit_params.original_url.is_empty()
-                                ? commit_params.original_url
-                                : common_params.url;
-  timing_info->name = initial_url.spec();
-  timing_info->start_time = common_params.navigation_start;
-  timing_info->allow_timing_details = response_head.timing_allow_passed;
-
-  // Only expose the response code when we are same origin and without
-  // cross-origin redirects
-  // https://fetch.spec.whatwg.org/#ref-for-concept-response-status%E2%91%A6
-  if (!IsCrossOriginResponseOrHasCrossOriginRedirects(
-          parent_origin, common_params, commit_params)) {
-    timing_info->response_status = commit_params.http_response_code;
-  }
-
-  // https://fetch.spec.whatwg.org/#create-an-opaque-timing-info
-  if (!timing_info->allow_timing_details) {
-    return timing_info;
-  }
-
-  timing_info->alpn_negotiated_protocol =
-      response_head.alpn_negotiated_protocol;
-  timing_info->connection_info = net::HttpResponseInfo::ConnectionInfoToString(
-      response_head.connection_info);
-
-  // If there's no received headers end time, don't set load timing. This is the
-  // case for non-HTTP requests, requests that don't go over the wire, and
-  // certain error cases.
-  // TODO(dcheng): Is it actually possible to hit this path if
-  // `response_head.headers` is populated?
-  if (!response_head.load_timing.receive_headers_end.is_null()) {
-    timing_info->timing = response_head.load_timing;
-  }
-  // `response_end` will be populated after loading the body.
-
-  DCHECK_EQ(commit_params.redirect_infos.size(),
-            commit_params.redirect_response.size());
-
-  if (!commit_params.redirect_infos.empty()) {
-    timing_info->last_redirect_end_time =
-        commit_params.redirect_response.back()->load_timing.receive_headers_end;
-  } else {
-    timing_info->last_redirect_end_time = base::TimeTicks();
-  }
-  // The final value for `encoded_body_size` and `decoded_body_size` will be
-  // populated after loading the body.
-  timing_info->did_reuse_connection = response_head.load_timing.socket_reused;
-  // Use url::Origin to handle cases like blob:https://.
-  timing_info->is_secure_transport = base::Contains(
-      url::GetSecureSchemes(), url::Origin::Create(common_params.url).scheme());
-  timing_info->allow_negative_values = false;
-  return timing_info;
-}
-}  // namespace content
diff --git a/content/browser/loader/resource_timing_utils.h b/content/browser/loader/resource_timing_utils.h
deleted file mode 100644
index 764495b..0000000
--- a/content/browser/loader/resource_timing_utils.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_LOADER_RESOURCE_TIMING_UTILS_H_
-#define CONTENT_BROWSER_LOADER_RESOURCE_TIMING_UTILS_H_
-
-#include "services/network/public/mojom/url_response_head.mojom-forward.h"
-#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-forward.h"
-#include "third_party/blink/public/mojom/navigation/navigation_params.mojom-forward.h"
-#include "third_party/blink/public/mojom/timing/resource_timing.mojom-forward.h"
-#include "url/origin.h"
-
-namespace content {
-
-blink::mojom::ResourceTimingInfoPtr GenerateResourceTimingForNavigation(
-    const url::Origin& parent_origin,
-    const blink::mojom::CommonNavigationParams& common_params,
-    const blink::mojom::CommitNavigationParams& commit_params,
-    const network::mojom::URLResponseHead& response_head);
-
-}  // namespace content
-
-#endif
diff --git a/content/browser/renderer_host/ipc_utils.cc b/content/browser/renderer_host/ipc_utils.cc
index 3a2dab5..aa8a0028 100644
--- a/content/browser/renderer_host/ipc_utils.cc
+++ b/content/browser/renderer_host/ipc_utils.cc
@@ -171,6 +171,16 @@
     return false;
   }
 
+  if (params->is_container_initiated) {
+    if (!current_rfh->GetParent() ||
+        (current_rfh->GetParent()->GetFrameToken() !=
+         params->initiator_frame_token)) {
+      mojo::ReportBadMessage(
+          "container initiated navigation from non-parent process");
+      return false;
+    }
+  }
+
   // Verification succeeded.
   return true;
 }
diff --git a/content/browser/renderer_host/navigation_controller_impl.cc b/content/browser/renderer_host/navigation_controller_impl.cc
index 358540b..b74775eb 100644
--- a/content/browser/renderer_host/navigation_controller_impl.cc
+++ b/content/browser/renderer_host/navigation_controller_impl.cc
@@ -2692,7 +2692,8 @@
     base::TimeTicks navigation_start_time,
     bool is_embedder_initiated_fenced_frame_navigation,
     bool is_unfenced_top_navigation,
-    bool force_new_browsing_instance) {
+    bool force_new_browsing_instance,
+    bool is_container_initiated) {
   if (is_renderer_initiated)
     DCHECK(initiator_origin.has_value());
 
@@ -2817,7 +2818,7 @@
           false /* has_user_gesture */, std::move(source_location),
           ReloadType::NONE, entry.get(), frame_entry.get(),
           navigation_start_time, is_embedder_initiated_fenced_frame_navigation,
-          is_unfenced_top_navigation);
+          is_unfenced_top_navigation, is_container_initiated);
 
   if (!request)
     return;
@@ -3760,7 +3761,8 @@
     FrameNavigationEntry* frame_entry,
     base::TimeTicks navigation_start_time,
     bool is_embedder_initiated_fenced_frame_navigation,
-    bool is_unfenced_top_navigation) {
+    bool is_unfenced_top_navigation,
+    bool is_container_initiated) {
   DCHECK_EQ(-1, GetIndexOfEntry(entry));
   DCHECK(frame_entry);
   // All renderer-initiated navigations must have an initiator_origin.
@@ -3931,7 +3933,8 @@
       params.is_form_submission,
       params.navigation_ui_data ? params.navigation_ui_data->Clone() : nullptr,
       params.impression, params.initiator_activation_and_ad_status,
-      params.is_pdf, is_embedder_initiated_fenced_frame_navigation);
+      params.is_pdf, is_embedder_initiated_fenced_frame_navigation,
+      is_container_initiated);
   navigation_request->set_from_download_cross_origin_redirect(
       params.from_download_cross_origin_redirect);
   navigation_request->set_force_new_browsing_instance(
diff --git a/content/browser/renderer_host/navigation_controller_impl.h b/content/browser/renderer_host/navigation_controller_impl.h
index ebb6afd8..ccdf116 100644
--- a/content/browser/renderer_host/navigation_controller_impl.h
+++ b/content/browser/renderer_host/navigation_controller_impl.h
@@ -227,7 +227,8 @@
       base::TimeTicks navigation_start_time,
       bool is_embedder_initiated_fenced_frame_navigation = false,
       bool is_unfenced_top_navigation = false,
-      bool force_new_browsing_instance = false);
+      bool force_new_browsing_instance = false,
+      bool is_container_initiated = false);
 
   // Navigates to the history entry associated with the given navigation API
   // |key|. Searches |entries_| for a FrameNavigationEntry associated with
@@ -653,7 +654,8 @@
       FrameNavigationEntry* frame_entry,
       base::TimeTicks navigation_start_time,
       bool is_embedder_initiated_fenced_frame_navigation = false,
-      bool is_unfenced_top_navigation = false);
+      bool is_unfenced_top_navigation = false,
+      bool is_container_initiated = false);
 
   // Creates and returns a NavigationRequest for a navigation to |entry|. Will
   // return nullptr if the parameters are invalid and the navigation cannot
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc
index 25aee529..e4b81f35 100644
--- a/content/browser/renderer_host/navigation_request.cc
+++ b/content/browser/renderer_host/navigation_request.cc
@@ -53,7 +53,6 @@
 #include "content/browser/loader/navigation_early_hints_manager.h"
 #include "content/browser/loader/navigation_url_loader.h"
 #include "content/browser/loader/object_navigation_fallback_body_loader.h"
-#include "content/browser/loader/resource_timing_utils.h"
 #include "content/browser/navigation_or_document_handle.h"
 #include "content/browser/network/cross_origin_embedder_policy_reporter.h"
 #include "content/browser/network/cross_origin_opener_policy_reporter.h"
@@ -141,6 +140,7 @@
 #include "services/network/public/cpp/web_sandbox_flags.h"
 #include "services/network/public/mojom/fetch_api.mojom.h"
 #include "services/network/public/mojom/supports_loading_mode.mojom.h"
+#include "services/network/public/mojom/url_response_head.mojom-forward.h"
 #include "services/network/public/mojom/url_response_head.mojom-shared.h"
 #include "services/network/public/mojom/url_response_head.mojom.h"
 #include "services/network/public/mojom/web_client_hints_types.mojom-shared.h"
@@ -170,6 +170,7 @@
 #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
 #include "third_party/blink/public/mojom/loader/mixed_content.mojom.h"
 #include "third_party/blink/public/mojom/loader/transferrable_url_loader.mojom.h"
+#include "third_party/blink/public/mojom/navigation/navigation_params.mojom-shared.h"
 #include "third_party/blink/public/mojom/navigation/navigation_params.mojom.h"
 #include "third_party/blink/public/mojom/navigation/prefetched_signed_exchange_info.mojom.h"
 #include "third_party/blink/public/mojom/runtime_feature_state/runtime_feature_state.mojom.h"
@@ -1099,7 +1100,8 @@
     blink::mojom::NavigationInitiatorActivationAndAdStatus
         initiator_activation_and_ad_status,
     bool is_pdf,
-    bool is_embedder_initiated_fenced_frame_navigation) {
+    bool is_embedder_initiated_fenced_frame_navigation,
+    bool is_container_initiated) {
   TRACE_EVENT1("navigation", "NavigationRequest::Create", "browser_initiated",
                browser_initiated);
 
@@ -1129,7 +1131,8 @@
       nullptr /* trust_token_params */, impression,
       base::TimeTicks() /* renderer_before_unload_start */,
       base::TimeTicks() /* renderer_before_unload_end */,
-      std::move(web_bundle_token_params), initiator_activation_and_ad_status);
+      std::move(web_bundle_token_params), initiator_activation_and_ad_status,
+      is_container_initiated);
 
   // Shift-Reload forces bypassing caches and service workers.
   if (common_params->navigation_type ==
@@ -1632,6 +1635,24 @@
     if (initiator_rfh)
       initiator_document_ = initiator_rfh->GetWeakDocumentPtr();
   }
+
+  // Spec: https://github.com/whatwg/html/issues/8846
+  // We only allow the parent to access a subframe resource timing if the
+  // navigation is container-initiated, e.g. iframe changed src.
+  if (begin_params_->is_container_initiated) {
+    // Only same-origin navigations without cross-origin redirects can
+    // expose response details (status-code / mime-type).
+    // https://github.com/whatwg/fetch/issues/1602
+    // Note that this condition checks this navigation is not cross origin.
+    // Cross-origin redirects are checked as part of OnRequestRedirected().
+    commit_params_->navigation_timing->parent_resource_timing_access =
+        GetParentFrame()->GetLastCommittedOrigin().IsSameOriginWith(GetURL())
+            ? blink::mojom::ParentResourceTimingAccess::
+                  kReportWithResponseDetails
+            : blink::mojom::ParentResourceTimingAccess::
+                  kReportWithoutResponseDetails;
+  }
+
   navigation_or_document_handle_ =
       NavigationOrDocumentHandle::CreateForNavigation(*this);
 
@@ -3067,6 +3088,18 @@
   const bool is_same_origin_redirect =
       url::Origin::Create(common_params_->url)
           .IsSameOriginWith(redirect_info.new_url);
+
+  // Only same-origin navigations without cross-origin redirects can
+  // expose response details (status-code / mime-type).
+  // https://github.com/whatwg/fetch/issues/1602
+  if (!is_same_origin_redirect &&
+      commit_params_->navigation_timing->parent_resource_timing_access ==
+          blink::mojom::ParentResourceTimingAccess::
+              kReportWithResponseDetails) {
+    commit_params_->navigation_timing->parent_resource_timing_access =
+        blink::mojom::ParentResourceTimingAccess::kReportWithoutResponseDetails;
+  }
+
   did_receive_early_hints_before_cross_origin_redirect_ |=
       did_create_early_hints_manager_params_ && !is_same_origin_redirect;
 
@@ -3789,6 +3822,12 @@
     return;
   }
 
+  // See https://github.com/whatwg/fetch/pull/1579
+  if (!response_head_->timing_allow_passed) {
+    commit_params_->navigation_timing->parent_resource_timing_access =
+        blink::mojom::ParentResourceTimingAccess::kDoNotReport;
+  }
+
   MaybeInjectIsolatedAppHeaders();
 
   {
@@ -4718,34 +4757,40 @@
     return;
   }
 
-  RenderFrameHostImpl* parent_rfh = GetParentFrame();
-
-  // Do not add ResourceTiming entries if the navigated URL does not have a
-  // parent.
-  if (!parent_rfh) {
-    return;
-  }
-
   // Some navigation are cancelled even before requesting and receiving a
   // response. Those cases are not supported and the ResourceTiming is not
   // reported to the parent.
-  if (!response_head_) {
+  if (!response()) {
     return;
   }
 
-  if (initiator_document_.AsRenderFrameHostIfValid() != parent_rfh) {
+  network::URLLoaderCompletionStatus status;
+  status.encoded_data_length = response()->encoded_data_length;
+  status.completion_time = base::TimeTicks::Now();
+  AddResourceTimingEntryForFailedSubframeNavigation(status);
+}
+
+void NavigationRequest::AddResourceTimingEntryForFailedSubframeNavigation(
+    const network::URLLoaderCompletionStatus& status) {
+  // For TAO-fail navigations, we would resort to fallback timing.
+  // See HTMLFrameOwnerElement::ReportFallbackResourceTimingIfNeeded().
+  DCHECK(response());
+  if (commit_params().navigation_timing->parent_resource_timing_access ==
+      blink::mojom::ParentResourceTimingAccess::kDoNotReport) {
     return;
   }
 
-  blink::mojom::ResourceTimingInfoPtr timing_info =
-      GenerateResourceTimingForNavigation(parent_rfh->GetLastCommittedOrigin(),
-                                          *common_params_, *commit_params_,
-                                          *response_head_);
-  timing_info->response_end = base::TimeTicks::Now();
-  parent_rfh->GetAssociatedLocalFrame()
-      ->AddResourceTimingEntryFromNonNavigatedFrame(
-          std::move(timing_info),
-          frame_tree_node()->frame_owner_element_type());
+  network::mojom::URLResponseHeadPtr response_head = response()->Clone();
+
+  bool allow_response_details =
+      commit_params().navigation_timing->parent_resource_timing_access ==
+      blink::mojom::ParentResourceTimingAccess::kReportWithResponseDetails;
+
+  GetParentFrame()->AddResourceTimingEntryForFailedSubframeNavigation(
+      frame_tree_node(), common_params().navigation_start,
+      commit_params().navigation_timing->redirect_end,
+      commit_params().original_url, common_params().url,
+      std::move(response_head), allow_response_details, status);
 }
 
 void NavigationRequest::OnRedirectChecksComplete(
@@ -4993,8 +5038,8 @@
       // fallback / resource timing are only reported if the navigation request
       // is logically still pending.
       ObjectNavigationFallbackBodyLoader::CreateAndStart(
-          *this, *common_params_, *commit_params_, *response(),
-          std::move(response_body_), std::move(url_loader_client_endpoints_),
+          *this, std::move(response_body_),
+          std::move(url_loader_client_endpoints_),
           base::BindOnce(&NavigationRequest::OnRequestFailedInternal,
                          weak_factory_.GetWeakPtr(),
                          network::URLLoaderCompletionStatus(net::ERR_ABORTED),
@@ -5016,6 +5061,7 @@
       result.action() == NavigationThrottle::CANCEL ||
       !response_should_be_rendered_) {
     MaybeAddResourceTimingEntryForCancelledNavigation();
+
     // Reset the RenderFrameHost that had been computed for the commit of the
     // navigation.
     render_frame_host_ = nullptr;
diff --git a/content/browser/renderer_host/navigation_request.h b/content/browser/renderer_host/navigation_request.h
index de4bb3c..e4980ab 100644
--- a/content/browser/renderer_host/navigation_request.h
+++ b/content/browser/renderer_host/navigation_request.h
@@ -260,7 +260,8 @@
       blink::mojom::NavigationInitiatorActivationAndAdStatus
           initiator_activation_and_ad_status,
       bool is_pdf,
-      bool is_embedder_initiated_fenced_frame_navigation = false);
+      bool is_embedder_initiated_fenced_frame_navigation = false,
+      bool is_container_initiated = false);
 
   // Creates a request for a renderer-initiated navigation.
   static std::unique_ptr<NavigationRequest> CreateRendererInitiated(
@@ -568,6 +569,11 @@
   // a request was made.
   void MaybeAddResourceTimingEntryForCancelledNavigation();
 
+  // Adds a resource timing entry to the parent in case of cancelled navigations
+  // and failed <object> navigations.
+  void AddResourceTimingEntryForFailedSubframeNavigation(
+      const network::URLLoaderCompletionStatus& status);
+
   // Lazily initializes and returns the mojo::NavigationClient interface used
   // for commit.
   mojom::NavigationClient* GetCommitNavigationClient();
diff --git a/content/browser/renderer_host/navigator.cc b/content/browser/renderer_host/navigator.cc
index fc5ddfc..d4868e7 100644
--- a/content/browser/renderer_host/navigator.cc
+++ b/content/browser/renderer_host/navigator.cc
@@ -872,7 +872,8 @@
     base::TimeTicks navigation_start_time,
     bool is_embedder_initiated_fenced_frame_navigation,
     bool is_unfenced_top_navigation,
-    bool force_new_browsing_instance) {
+    bool force_new_browsing_instance,
+    bool is_container_initiated) {
   // |method != "POST"| should imply absence of |post_body|.
   if (method != "POST" && post_body) {
     NOTREACHED();
@@ -917,7 +918,7 @@
       std::move(blob_url_loader_factory), is_form_submission, impression,
       initiator_activation_and_ad_status, navigation_start_time,
       is_embedder_initiated_fenced_frame_navigation, is_unfenced_top_navigation,
-      force_new_browsing_instance);
+      force_new_browsing_instance, is_container_initiated);
 }
 
 void Navigator::BeforeUnloadCompleted(FrameTreeNode* frame_tree_node,
diff --git a/content/browser/renderer_host/navigator.h b/content/browser/renderer_host/navigator.h
index e3bd62d..f344ec2 100644
--- a/content/browser/renderer_host/navigator.h
+++ b/content/browser/renderer_host/navigator.h
@@ -165,7 +165,8 @@
       base::TimeTicks navigation_start_time,
       bool is_embedder_initiated_fenced_frame_navigation = false,
       bool is_unfenced_top_navigation = false,
-      bool force_new_browsing_instance = false);
+      bool force_new_browsing_instance = false,
+      bool is_container_initiated = false);
 
   // Called after BeforeUnloadCompleted callback is invoked from the renderer.
   // If |frame_tree_node| has a NavigationRequest waiting for the renderer
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index 8fc55d9..ba6b172 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -8287,6 +8287,17 @@
     return;
   }
 
+  // Container-initiated navigations must come from the same process as the
+  // parent.
+  if (begin_params->is_container_initiated) {
+    if (!GetParent() ||
+        (initiator_process_id != GetParent()->GetProcess()->GetID())) {
+      mojo::ReportBadMessage(
+          "container initiated navigation from non-parent process");
+      return;
+    }
+  }
+
   // If the request is bearing Private State Tokens parameters:
   // - it must not be a main-frame navigation, and
   // - for certain Private State Tokens operations, the frame's parent needs the
@@ -9777,6 +9788,48 @@
          navigation_request->DidEncounterError());
 }
 
+void RenderFrameHostImpl::AddResourceTimingEntryForFailedSubframeNavigation(
+    FrameTreeNode* child_frame,
+    base::TimeTicks start_time,
+    base::TimeTicks redirect_time,
+    const GURL& initial_url,
+    const GURL& final_url,
+    network::mojom::URLResponseHeadPtr response_head,
+    bool allow_response_details,
+    const network::URLLoaderCompletionStatus& completion_status) {
+  uint32_t status_code = 0;
+  std::string mime_type;
+  std::string normalized_server_timing;
+
+  response_head->headers->GetNormalizedHeader("Server-Timing",
+                                              &normalized_server_timing);
+
+  if (allow_response_details) {
+    status_code = response_head->headers->response_code();
+    mime_type = response_head->mime_type;
+  }
+
+  // To avoid cross-origin leaks, make sure to only to pass here data that
+  // is OK when TAO-gated (as in, timing information only).
+
+  absl::optional<blink::FrameToken> child_token_in_parent =
+      child_frame->GetRenderFrameHostManager()
+          .GetFrameTokenForSiteInstanceGroup(GetSiteInstance()->group());
+
+  if (!child_token_in_parent) {
+    return;
+  }
+
+  GetAssociatedLocalFrame()->AddResourceTimingEntryForFailedSubframeNavigation(
+      child_token_in_parent.value(), initial_url, start_time, redirect_time,
+      response_head->request_start, response_head->response_start, status_code,
+      mime_type, response_head->load_timing, response_head->connection_info,
+      response_head->alpn_negotiated_protocol,
+      base::Contains(url::GetSecureSchemes(),
+                     url::Origin::Create(final_url).scheme()),
+      response_head->is_validated, normalized_server_timing, completion_status);
+}
+
 void RenderFrameHostImpl::HandleRendererDebugURL(const GURL& url) {
   DCHECK(blink::IsRendererDebugURL(url));
 
diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/browser/renderer_host/render_frame_host_impl.h
index a4de7f3e..acf65aef 100644
--- a/content/browser/renderer_host/render_frame_host_impl.h
+++ b/content/browser/renderer_host/render_frame_host_impl.h
@@ -1438,6 +1438,16 @@
       const absl::optional<std::string>& error_page_content,
       const blink::DocumentToken& document_token);
 
+  void AddResourceTimingEntryForFailedSubframeNavigation(
+      FrameTreeNode* child_frame,
+      base::TimeTicks start_time,
+      base::TimeTicks redirect_time,
+      const GURL& initial_url,
+      const GURL& final_url,
+      network::mojom::URLResponseHeadPtr response_head,
+      bool allow_response_details,
+      const network::URLLoaderCompletionStatus& completion_status);
+
   // Sends a renderer-debug URL to the renderer process for handling.
   void HandleRendererDebugURL(const GURL& url);
 
diff --git a/content/browser/renderer_host/render_frame_proxy_host.cc b/content/browser/renderer_host/render_frame_proxy_host.cc
index b9ddf05..824e7cc 100644
--- a/content/browser/renderer_host/render_frame_proxy_host.cc
+++ b/content/browser/renderer_host/render_frame_proxy_host.cc
@@ -703,7 +703,10 @@
       params->extra_headers, std::move(blob_url_loader_factory),
       std::move(params->source_location), params->user_gesture,
       params->is_form_submission, params->impression,
-      params->initiator_activation_and_ad_status, navigation_start_time);
+      params->initiator_activation_and_ad_status, navigation_start_time,
+      /*is_embedder_initiated_fenced_frame_navigation=*/false,
+      /*is_unfenced_top_navigation=*/false,
+      /*force_new_browsing_instance=*/false, params->is_container_initiated);
 }
 
 void RenderFrameProxyHost::UpdateViewportIntersection(
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc
index 9815447..aefb3d9 100644
--- a/content/browser/security_exploit_browsertest.cc
+++ b/content/browser/security_exploit_browsertest.cc
@@ -1540,7 +1540,8 @@
           base::TimeTicks() /* renderer_before_unload_end */,
           absl::nullopt /* web_bundle_token */,
           blink::mojom::NavigationInitiatorActivationAndAdStatus::
-              kDidNotStartWithTransientActivation);
+              kDidNotStartWithTransientActivation,
+          false /* is_container_initiated */);
 
   // Receiving the invalid IPC message should lead to renderer process
   // termination.
diff --git a/content/common/frame.mojom b/content/common/frame.mojom
index d2f7102..4fbba74 100644
--- a/content/common/frame.mojom
+++ b/content/common/frame.mojom
@@ -17,6 +17,7 @@
 import "skia/public/mojom/skcolor.mojom";
 import "services/network/public/mojom/content_security_policy.mojom";
 import "services/network/public/mojom/url_loader.mojom";
+import "services/network/public/mojom/url_loader_completion_status.mojom";
 import "services/network/public/mojom/url_loader_factory.mojom";
 import "services/network/public/mojom/url_request.mojom";
 import "services/network/public/mojom/url_response_head.mojom";
diff --git a/content/public/test/fake_local_frame.cc b/content/public/test/fake_local_frame.cc
index f8191976..f648ddf 100644
--- a/content/public/test/fake_local_frame.cc
+++ b/content/public/test/fake_local_frame.cc
@@ -9,7 +9,6 @@
 #include "third_party/blink/public/mojom/devtools/inspector_issue.mojom.h"
 #include "third_party/blink/public/mojom/frame/media_player_action.mojom.h"
 #include "third_party/blink/public/mojom/push_messaging/push_messaging.mojom.h"
-#include "third_party/blink/public/mojom/timing/resource_timing.mojom.h"
 
 #if BUILDFLAG(IS_MAC)
 #include "ui/base/mojom/attributed_string.mojom.h"
@@ -79,15 +78,6 @@
     const std::vector<blink::mojom::WebFeature>&) {}
 
 void FakeLocalFrame::RenderFallbackContent() {}
-
-void FakeLocalFrame::AddResourceTimingEntryFromNonNavigatedFrame(
-    blink::mojom::ResourceTimingInfoPtr timing,
-    blink::FrameOwnerElementType parent_frame_element_type) {}
-
-void FakeLocalFrame::RenderFallbackContentWithResourceTiming(
-    blink::mojom::ResourceTimingInfoPtr,
-    const std::string& server_timing_value) {}
-
 void FakeLocalFrame::BeforeUnload(bool is_reload,
                                   BeforeUnloadCallback callback) {
   base::TimeTicks now = base::TimeTicks::Now();
@@ -204,6 +194,23 @@
 void FakeLocalFrame::SnapshotDocumentForViewTransition(
     SnapshotDocumentForViewTransitionCallback callback) {}
 
+void FakeLocalFrame::AddResourceTimingEntryForFailedSubframeNavigation(
+    const ::blink::FrameToken& subframe_token,
+    const GURL& initial_url,
+    ::base::TimeTicks start_time,
+    ::base::TimeTicks redirect_time,
+    ::base::TimeTicks request_start,
+    ::base::TimeTicks response_start,
+    uint32_t response_code,
+    const std::string& mime_type,
+    const ::net::LoadTimingInfo& load_timing_info,
+    ::net::HttpResponseInfo::ConnectionInfo connection_info,
+    const std::string& alpn_negotiated_protocol,
+    bool is_secure_transport,
+    bool is_validated,
+    const std::string& normalized_server_timing,
+    const ::network::URLLoaderCompletionStatus& completion_status) {}
+
 void FakeLocalFrame::BindFrameHostReceiver(
     mojo::ScopedInterfaceEndpointHandle handle) {
   receiver_.Bind(mojo::PendingAssociatedReceiver<blink::mojom::LocalFrame>(
diff --git a/content/public/test/fake_local_frame.h b/content/public/test/fake_local_frame.h
index e732e63..8930e12 100644
--- a/content/public/test/fake_local_frame.h
+++ b/content/public/test/fake_local_frame.h
@@ -8,6 +8,8 @@
 #include "build/build_config.h"
 #include "mojo/public/cpp/bindings/associated_receiver_set.h"
 #include "mojo/public/cpp/bindings/pending_associated_receiver.h"
+#include "net/http/http_response_info.h"
+#include "services/network/public/mojom/load_timing_info.mojom.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
 #include "third_party/blink/public/common/messaging/transferable_message.h"
@@ -65,12 +67,6 @@
   void ReportBlinkFeatureUsage(
       const std::vector<blink::mojom::WebFeature>&) override;
   void RenderFallbackContent() override;
-  void AddResourceTimingEntryFromNonNavigatedFrame(
-      blink::mojom::ResourceTimingInfoPtr timing,
-      blink::FrameOwnerElementType parent_frame_element_type) override;
-  void RenderFallbackContentWithResourceTiming(
-      blink::mojom::ResourceTimingInfoPtr,
-      const std::string& server_timing_value) override;
   void BeforeUnload(bool is_reload, BeforeUnloadCallback callback) override;
   void MediaPlayerActionAt(const gfx::Point& location,
                            blink::mojom::MediaPlayerActionPtr action) override;
@@ -150,6 +146,22 @@
                          blink::mojom::TraverseCancelledReason reason) override;
   void SnapshotDocumentForViewTransition(
       SnapshotDocumentForViewTransitionCallback callback) override;
+  void AddResourceTimingEntryForFailedSubframeNavigation(
+      const ::blink::FrameToken& subframe_token,
+      const GURL& initial_url,
+      base::TimeTicks start_time,
+      base::TimeTicks redirect_time,
+      base::TimeTicks request_start,
+      base::TimeTicks response_start,
+      uint32_t response_code,
+      const std::string& mime_type,
+      const net::LoadTimingInfo& load_timing_info,
+      net::HttpResponseInfo::ConnectionInfo connection_info,
+      const std::string& alpn_negotiated_protocol,
+      bool is_secure_transport,
+      bool is_validated,
+      const std::string& normalized_server_timing,
+      const ::network::URLLoaderCompletionStatus& completion_status) override;
 
  private:
   void BindFrameHostReceiver(mojo::ScopedInterfaceEndpointHandle handle);
diff --git a/content/public/test/fake_remote_frame.cc b/content/public/test/fake_remote_frame.cc
index 9492218..04d8a077 100644
--- a/content/public/test/fake_remote_frame.cc
+++ b/content/public/test/fake_remote_frame.cc
@@ -63,10 +63,6 @@
 
 void FakeRemoteFrame::RenderFallbackContent() {}
 
-void FakeRemoteFrame::RenderFallbackContentWithResourceTiming(
-    blink::mojom::ResourceTimingInfoPtr,
-    const std::string& server_timing_value) {}
-
 void FakeRemoteFrame::AddResourceTimingFromChild(
     blink::mojom::ResourceTimingInfoPtr timing) {}
 
diff --git a/content/public/test/fake_remote_frame.h b/content/public/test/fake_remote_frame.h
index e8174cd2..1521517b 100644
--- a/content/public/test/fake_remote_frame.h
+++ b/content/public/test/fake_remote_frame.h
@@ -64,9 +64,6 @@
       const base::UnguessableToken& embedding_token) override;
   void SetPageFocus(bool is_focused) override;
   void RenderFallbackContent() override;
-  void RenderFallbackContentWithResourceTiming(
-      blink::mojom::ResourceTimingInfoPtr,
-      const std::string& server_timing_value) override;
   void AddResourceTimingFromChild(
       blink::mojom::ResourceTimingInfoPtr timing) override;
 
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 0569890..24fced83 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -944,6 +944,8 @@
       browser_navigation_timings.fetch_start;
 
   renderer_navigation_timings.input_start = input_start;
+  renderer_navigation_timings.parent_resource_timing_access =
+      browser_navigation_timings.parent_resource_timing_access;
 
   return renderer_navigation_timings;
 }
@@ -5757,7 +5759,7 @@
               : nullptr,
           info->impression, renderer_before_unload_start,
           renderer_before_unload_end, web_bundle_token_params,
-          initiator_activation_and_ad_status);
+          initiator_activation_and_ad_status, info->is_container_initiated);
 
   mojo::PendingAssociatedRemote<mojom::NavigationClient>
       navigation_client_remote;
diff --git a/content/test/navigation_simulator_impl.cc b/content/test/navigation_simulator_impl.cc
index 69de66c..d1c7e3ef 100644
--- a/content/test/navigation_simulator_impl.cc
+++ b/content/test/navigation_simulator_impl.cc
@@ -1323,7 +1323,8 @@
           base::TimeTicks() /* renderer_before_unload_end */,
           absl::nullopt /* web_bundle_token */,
           blink::mojom::NavigationInitiatorActivationAndAdStatus::
-              kDidNotStartWithTransientActivation);
+              kDidNotStartWithTransientActivation,
+          false /* is_container_initiated */);
   auto common_params = blink::CreateCommonNavigationParams();
   common_params->navigation_start = base::TimeTicks::Now();
   common_params->input_start = navigation_input_start_;
diff --git a/content/test/test_render_frame_host.cc b/content/test/test_render_frame_host.cc
index 0491d69..3cdfea02 100644
--- a/content/test/test_render_frame_host.cc
+++ b/content/test/test_render_frame_host.cc
@@ -419,7 +419,8 @@
           base::TimeTicks() /* renderer_before_unload_end */,
           absl::nullopt /* web_bundle_token */,
           blink::mojom::NavigationInitiatorActivationAndAdStatus::
-              kDidNotStartWithTransientActivation);
+              kDidNotStartWithTransientActivation,
+          false /* is_container_initiated */);
   auto common_params = blink::CreateCommonNavigationParams();
   common_params->url = url;
   common_params->initiator_origin = GetLastCommittedOrigin();