// Copyright 2013 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/renderer/render_frame_impl.h"

#include <algorithm>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <utility>
#include <vector>

#include "base/byte_count.h"
#include "base/check_deref.h"
#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/containers/flat_map.h"
#include "base/containers/to_vector.h"
#include "base/debug/alias.h"
#include "base/debug/asan_invalid_access.h"
#include "base/debug/crash_logging.h"
#include "base/debug/dump_without_crashing.h"
#include "base/feature_list.h"
#include "base/files/file.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ref.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
#include "base/observer_list.h"
#include "base/process/process.h"
#include "base/run_loop.h"
#include "base/strings/strcat.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/time/time.h"
#include "base/timer/elapsed_timer.h"
#include "base/trace_event/trace_event.h"
#include "base/types/optional_util.h"
#include "base/unguessable_token.h"
#include "base/uuid.h"
#include "base/values.h"
#include "build/build_config.h"
#include "cc/base/switches.h"
#include "components/history/core/browser/features.h"
#include "content/common/associated_interfaces.mojom.h"
#include "content/common/content_navigation_policy.h"
#include "content/common/content_switches_internal.h"
#include "content/common/debug_utils.h"
#include "content/common/features.h"
#include "content/common/frame.mojom.h"
#include "content/common/frame_messages.mojom.h"
#include "content/common/main_frame_counter.h"
#include "content/common/navigation_client.mojom.h"
#include "content/common/navigation_gesture.h"
#include "content/common/navigation_params_utils.h"
#include "content/common/renderer_host.mojom.h"
#include "content/common/web_package/signed_exchange_utils.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/extra_mojo_js_features.mojom.h"
#include "content/public/common/isolated_world_ids.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/public/renderer/render_frame_observer.h"
#include "content/public/renderer/render_frame_visitor.h"
#include "content/public/renderer/render_thread.h"
#include "content/public/renderer/window_features_converter.h"
#include "content/renderer/accessibility/ax_tree_snapshotter_impl.h"
#include "content/renderer/accessibility/render_accessibility_impl.h"
#include "content/renderer/accessibility/render_accessibility_manager.h"
#include "content/renderer/agent_scheduling_group.h"
#include "content/renderer/background_resource_fetch_assets.h"
#include "content/renderer/content_security_policy_util.h"
#include "content/renderer/document_state.h"
#include "content/renderer/dom_automation_controller.h"
#include "content/renderer/effective_connection_type_helper.h"
#include "content/renderer/frame_owner_properties_converter.h"
#include "content/renderer/gpu_benchmarking_extension.h"
#include "content/renderer/local_resource_url_loader_factory.h"
#include "content/renderer/media/media_permission_dispatcher.h"
#include "content/renderer/mhtml_handle_writer.h"
#include "content/renderer/mojo/blink_interface_registry_impl.h"
#include "content/renderer/navigation_client.h"
#include "content/renderer/navigation_state.h"
#include "content/renderer/policy_container_util.h"
#include "content/renderer/render_process.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/renderer_blink_platform_impl.h"
#include "content/renderer/renderer_navigation_metrics_manager.h"
#include "content/renderer/service_worker/service_worker_network_provider_for_frame.h"
#include "content/renderer/service_worker/web_service_worker_provider_impl.h"
#include "content/renderer/skia_benchmarking_extension.h"
#include "content/renderer/stats_collection_controller.h"
#include "content/renderer/v8_value_converter_impl.h"
#include "content/renderer/web_ui_extension.h"
#include "content/renderer/web_ui_extension_data.h"
#include "content/renderer/worker/dedicated_worker_host_factory_client.h"
#include "crypto/sha2.h"
#include "ipc/constants.mojom.h"
#include "media/mojo/mojom/audio_processing.mojom.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "net/base/data_url.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "services/network/public/cpp/content_decoding_interceptor.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/not_implemented_url_loader_factory.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/public/mojom/fetch_api.mojom.h"
#include "services/network/public/mojom/restricted_cookie_manager.mojom.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "services/service_manager/public/mojom/interface_provider.mojom.h"
#include "services/tracing/public/cpp/perfetto/track_name_recorder.h"
#include "services/viz/public/cpp/gpu/context_provider_command_buffer.h"
#include "third_party/abseil-cpp/absl/container/flat_hash_map.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/common/chrome_debug_urls.h"
#include "third_party/blink/public/common/context_menu_data/context_menu_data.h"
#include "third_party/blink/public/common/context_menu_data/untrustworthy_context_menu_params.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/input/web_keyboard_event.h"
#include "third_party/blink/public/common/interest_group/ad_auction_constants.h"
#include "third_party/blink/public/common/loader/loader_constants.h"
#include "third_party/blink/public/common/loader/record_load_histograms.h"
#include "third_party/blink/public/common/loader/resource_type_util.h"
#include "third_party/blink/public/common/loader/url_loader_throttle.h"
#include "third_party/blink/public/common/navigation/impression.h"
#include "third_party/blink/public/common/navigation/navigation_params.h"
#include "third_party/blink/public/common/navigation/navigation_params_mojom_traits.h"
#include "third_party/blink/public/common/navigation/navigation_policy.h"
#include "third_party/blink/public/common/page_state/page_state.h"
#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/blob/blob.mojom.h"
#include "third_party/blink/public/mojom/blob/blob_url_store.mojom.h"
#include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
#include "third_party/blink/public/mojom/dom_storage/storage_area.mojom.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
#include "third_party/blink/public/mojom/frame/frame.mojom.h"
#include "third_party/blink/public/mojom/frame/frame_owner_properties.mojom.h"
#include "third_party/blink/public/mojom/frame/user_activation_notification_type.mojom.h"
#include "third_party/blink/public/mojom/frame/user_activation_update_types.mojom.h"
#include "third_party/blink/public/mojom/frame/view_transition_state.mojom.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom.h"
#include "third_party/blink/public/mojom/input/input_handler.mojom-shared.h"
#include "third_party/blink/public/mojom/loader/fetch_later.mojom.h"
#include "third_party/blink/public/mojom/loader/referrer.mojom.h"
#include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom.h"
#include "third_party/blink/public/mojom/loader/resource_load_info.mojom.h"
#include "third_party/blink/public/mojom/navigation/navigation_params.mojom.h"
#include "third_party/blink/public/mojom/page/widget.mojom.h"
#include "third_party/blink/public/mojom/permissions/permission.mojom.h"
#include "third_party/blink/public/mojom/render_accessibility.mojom.h"
#include "third_party/blink/public/mojom/renderer_preference_watcher.mojom.h"
#include "third_party/blink/public/mojom/widget/platform_widget.mojom.h"
#include "third_party/blink/public/platform/file_path_conversion.h"
#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h"
#include "third_party/blink/public/platform/resource_load_info_notifier_wrapper.h"
#include "third_party/blink/public/platform/scheduler/web_agent_group_scheduler.h"
#include "third_party/blink/public/platform/tracked_child_url_loader_factory_bundle.h"
#include "third_party/blink/public/platform/url_conversion.h"
#include "third_party/blink/public/platform/weak_wrapper_resource_load_info_notifier.h"
#include "third_party/blink/public/platform/web_data.h"
#include "third_party/blink/public/platform/web_dedicated_or_shared_worker_global_scope_context.h"
#include "third_party/blink/public/platform/web_http_body.h"
#include "third_party/blink/public/platform/web_media_player.h"
#include "third_party/blink/public/platform/web_media_player_source.h"
#include "third_party/blink/public/platform/web_navigation_body_loader.h"
#include "third_party/blink/public/platform/web_runtime_features.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/public/platform/web_url_error.h"
#include "third_party/blink/public/platform/web_url_request_extra_data.h"
#include "third_party/blink/public/platform/web_url_request_util.h"
#include "third_party/blink/public/platform/web_url_response.h"
#include "third_party/blink/public/web/blink.h"
#include "third_party/blink/public/web/modules/media/audio/audio_device_factory.h"
#include "third_party/blink/public/web/modules/media/audio/audio_output_ipc_factory.h"
#include "third_party/blink/public/web/modules/mediastream/web_media_stream_device_observer.h"
#include "third_party/blink/public/web/web_autofill_client.h"
#include "third_party/blink/public/web/web_console_message.h"
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_element_collection.h"
#include "third_party/blink/public/web/web_frame_owner_properties.h"
#include "third_party/blink/public/web/web_frame_serializer.h"
#include "third_party/blink/public/web/web_frame_widget.h"
#include "third_party/blink/public/web/web_input_method_controller.h"
#include "third_party/blink/public/web/web_link_preview_triggerer.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_navigation_control.h"
#include "third_party/blink/public/web/web_navigation_policy.h"
#include "third_party/blink/public/web/web_navigation_timings.h"
#include "third_party/blink/public/web/web_navigation_type.h"
#include "third_party/blink/public/web/web_performance_metrics_for_nested_contexts.h"
#include "third_party/blink/public/web/web_picture_in_picture_window_options.h"
#include "third_party/blink/public/web/web_plugin.h"
#include "third_party/blink/public/web/web_plugin_container.h"
#include "third_party/blink/public/web/web_plugin_document.h"
#include "third_party/blink/public/web/web_plugin_params.h"
#include "third_party/blink/public/web/web_range.h"
#include "third_party/blink/public/web/web_remote_frame.h"
#include "third_party/blink/public/web/web_savable_resources_test_support.h"
#include "third_party/blink/public/web/web_script_source.h"
#include "third_party/blink/public/web/web_searchable_form_data.h"
#include "third_party/blink/public/web/web_security_policy.h"
#include "third_party/blink/public/web/web_serialized_script_value.h"
#include "third_party/blink/public/web/web_v8_features.h"
#include "third_party/blink/public/web/web_view.h"
#include "third_party/blink/public/web/web_widget.h"
#include "third_party/blink/public/web/web_window_features.h"
#include "third_party/perfetto/include/perfetto/tracing/track.h"
#include "ui/accessibility/ax_tree_update.h"
#include "ui/events/base_event_utils.h"
#include "url/origin.h"
#include "url/url_constants.h"
#include "url/url_util.h"
#include "v8/include/v8-isolate.h"
#include "v8/include/v8-local-handle.h"
#include "v8/include/v8-microtask-queue.h"

#if BUILDFLAG(IS_ANDROID)
#include <cpu-features.h>

#include "content/renderer/java/gin_java_bridge_dispatcher.h"
#include "mojo/public/cpp/bindings/self_owned_associated_receiver.h"
#endif

using base::Time;
using blink::ContextMenuData;
using blink::WebContentDecryptionModule;
using blink::WebData;
using blink::WebDocument;
using blink::WebDocumentLoader;
using blink::WebDOMMessageEvent;
using blink::WebElement;
using blink::WebElementCollection;
using blink::WebFrame;
using blink::WebFrameLoadType;
using blink::WebFrameSerializer;
using blink::WebFrameSerializerClient;
using blink::WebHistoryItem;
using blink::WebHTTPBody;
using blink::WebInputMethodController;
using blink::WebLocalFrame;
using blink::WebMediaPlayer;
using blink::WebMediaPlayerClient;
using blink::WebMediaPlayerEncryptedMediaClient;
using blink::WebNavigationParams;
using blink::WebNavigationPolicy;
using blink::WebNavigationType;
using blink::WebNode;
using blink::WebPluginDocument;
using blink::WebPluginParams;
using blink::WebRange;
using blink::WebScriptSource;
using blink::WebSearchableFormData;
using blink::WebSecurityOrigin;
using blink::WebSecurityPolicy;
using blink::WebSerializedScriptValue;
using blink::WebServiceWorkerProvider;
using blink::WebString;
using blink::WebThreadSafeData;
using blink::WebURL;
using blink::WebURLError;
using blink::WebURLRequest;
using blink::WebURLResponse;
using blink::WebView;
using blink::mojom::SelectionMenuBehavior;
using network::mojom::ReferrerPolicy;

namespace content {

namespace {

// Feature to combine the UpdateState IPC that's sent during commit time with
// the DidCommit* IPCs. See: http://crbug.com/424829233
BASE_FEATURE(kReducePageStateIpcs, base::FEATURE_ENABLED_BY_DEFAULT);

const int kExtraCharsBeforeAndAfterSelection = 100;
const size_t kMaxURLLogChars = 1024;
const char kCommitRenderFrame[] = "Navigation.CommitRenderFrame";

// Time, in seconds, we delay before sending content state changes (such as form
// state and scroll position) to the browser. We delay sending changes to avoid
// spamming the browser.
// To avoid having tab/session restore require sending a message to get the
// current content state during tab closing we use a shorter timeout for the
// foreground renderer. This means there is a small window of time from which
// content state is modified and not sent to session restore, but this is
// better than having to wake up all renderers during shutdown.
constexpr base::TimeDelta kDelaySecondsForContentStateSyncHidden =
    base::Seconds(5);
constexpr base::TimeDelta kDelaySecondsForContentStateSync = base::Seconds(1);

using FrameMap = absl::flat_hash_map<blink::WebFrame*, RenderFrameImpl*>;
base::LazyInstance<FrameMap>::DestructorAtExit g_frame_map =
    LAZY_INSTANCE_INITIALIZER;

// Please keep in sync with "RendererBlockedURLReason" in
// tools/metrics/histograms/metadata/navigation/enums.xml. These values are
// persisted to logs. Entries should not be renumbered and numeric values should
// never be reused.
enum class RendererBlockedURLReason {
  kInvalidURL = 0,
  kTooLongURL = 1,
  kBadAboutURL = 2,

  kMaxValue = kBadAboutURL
};

int64_t ExtractPostId(const WebHistoryItem& item) {
  if (item.IsNull() || item.HttpBody().IsNull())
    return -1;

  return item.HttpBody().Identifier();
}

std::string TrimURL(const std::string& url) {
  if (url.length() <= kMaxURLLogChars)
    return url;
  return url.substr(0, kMaxURLLogChars - 3) + "...";
}

// Calculates transition type based on navigation parameters. Used
// during navigation, before WebDocumentLoader is available.
ui::PageTransition GetTransitionType(ui::PageTransition default_transition,
                                     bool replaces_current_item,
                                     bool is_main_frame,
                                     bool is_in_fenced_frame_tree,
                                     WebNavigationType navigation_type) {
  if (is_in_fenced_frame_tree) {
    // Navigations inside fenced frame trees do not add session history items
    // and must be marked with PAGE_TRANSITION_AUTO_SUBFRAME. This is set
    // regardless of the `is_main_frame` value since this is inside a fenced
    // frame tree and should behave the same as iframes.
    return ui::PAGE_TRANSITION_AUTO_SUBFRAME;
  }
  if (replaces_current_item && !is_main_frame) {
    // Subframe navigations that don't add session history items must be
    // marked with AUTO_SUBFRAME. See also DidFailProvisionalLoad for how we
    // handle loading of error pages.
    return ui::PAGE_TRANSITION_AUTO_SUBFRAME;
  }
  bool is_form_submit =
      navigation_type == blink::kWebNavigationTypeFormSubmitted ||
      navigation_type == blink::kWebNavigationTypeFormResubmittedBackForward ||
      navigation_type == blink::kWebNavigationTypeFormResubmittedReload;
  if (ui::PageTransitionCoreTypeIs(default_transition,
                                   ui::PAGE_TRANSITION_LINK) &&
      is_form_submit) {
    return ui::PAGE_TRANSITION_FORM_SUBMIT;
  }
  return default_transition;
}

// Calculates transition type for the specific document loaded using
// WebDocumentLoader. Used while loading subresources.
ui::PageTransition GetTransitionType(blink::WebDocumentLoader* document_loader,
                                     bool is_main_frame,
                                     bool is_in_fenced_frame_tree) {
  NavigationState* navigation_state =
      DocumentState::FromDocumentLoader(document_loader)->navigation_state();
  ui::PageTransition default_transition =
      navigation_state->IsForSynchronousCommit()
          ? ui::PAGE_TRANSITION_LINK
          : ui::PageTransitionFromInt(
                navigation_state->common_params().transition);
  if (!is_in_fenced_frame_tree && navigation_state->WasWithinSameDocument())
    return default_transition;
  return GetTransitionType(default_transition,
                           document_loader->ReplacesCurrentHistoryItem(),
                           is_main_frame, is_in_fenced_frame_tree,
                           document_loader->GetNavigationType());
}

// Ensure that the renderer does not send commit URLs to the browser process
// that are known to be unsupported. Ideally these would be caught earlier in
// Blink and not get this far. Histograms are reported (similar to those in
// RenderProcessHostImpl::FilterURL) to track the cases that should be handled
// earlier. See https://crbug.com/40066983.
bool IsValidCommitUrl(const GURL& url) {
  // Invalid URLs are not accepted by the browser process.
  if (!url.is_valid()) {
    base::UmaHistogramEnumeration("Navigation.Renderer.BlockedForFilterURL",
                                  RendererBlockedURLReason::kInvalidURL);
    return false;
  }

  // Do not send a URL longer than Mojo will serialize.
  if (url.possibly_invalid_spec().length() > url::kMaxURLChars) {
    base::UmaHistogramEnumeration("Navigation.Renderer.BlockedForFilterURL",
                                  RendererBlockedURLReason::kTooLongURL);
    return false;
  }

  // Any about: URLs must be either about:blank or about:srcdoc (optionally with
  // fragments).
  if (url.SchemeIs(url::kAboutScheme) &&
      (!url.IsAboutBlank() && !url.IsAboutSrcdoc())) {
    base::UmaHistogramEnumeration("Navigation.Renderer.BlockedForFilterURL",
                                  RendererBlockedURLReason::kBadAboutURL);
    return false;
  }

  return true;
}

// Gets URL that should override the default getter for this data source
// (if any), storing it in |output|. Returns true if there is an override URL.
bool MaybeGetOverriddenURL(WebDocumentLoader* document_loader, GURL* output) {
  DocumentState* document_state =
      DocumentState::FromDocumentLoader(document_loader);
  // `document_state` may be null if it was taken from the loader, e.g. when
  // committing the result of evaluating a javascript: URL,
  // `FrameLoader::CommitNavigation()` takes the `DocumentState`. Early
  // returning here means the answer may be inaccurate, but this can only
  // happen when the replaced `Document` is being detached and about to go
  // away.
  if (!document_state) {
    return false;
  }

  // If this document is loaded by a loadDataWithBaseURL request, then the URLs
  // saved in the DocumentLoader will be the user-supplied base URL (used as the
  // "document URL") and history URL (used as the "unreachable URL"/"URL for
  // history"). However, we want to return the data: URL (the URL originally
  // sent by the browser to commit the navigation) here.
  // TODO(crbug.com/40187600): Since the DocumentState stays as long as
  // the Document stays the same, this means the data: URL will be returned even
  // after same-document navigations. Investigate whether this is intended or
  // not.
  if (document_state->was_load_data_with_base_url_request()) {
    *output = document_state->data_url();
    return true;
  }

  // The "unreachable URL" is only set in two cases:
  // - An error page, where the "unreachable URL" is set to the URL that failed
  // to load. We want the URL bar to show that URL, and the session history
  // entry should also use that URL (instead of "chrome-error://chromewebdata"
  // which is used as the "document URL" for the DocumentLoader).
  // - A loadDataWithBaseURL, where the "unreachable URL" is set to the "history
  // URL". This case should never reach this point as it's handled above, where
  // we return the original data: URL instead.
  if (document_loader->HasUnreachableURL()) {
    *output = document_loader->UnreachableWebURL();
    return true;
  }

  return false;
}

// Returns false unless this is a top-level navigation.
bool IsTopLevelNavigation(WebFrame* frame) {
  return frame->Parent() == nullptr && !frame->View()->IsFencedFrameRoot();
}

void FillNavigationParamsRequest(
    const blink::mojom::CommonNavigationParams& common_params,
    const blink::mojom::CommitNavigationParams& commit_params,
    blink::WebNavigationParams* navigation_params) {
  // Use the original navigation url to start with. We'll replay the redirects
  // afterwards and will eventually arrive to the final url.
  navigation_params->url = !commit_params.original_url.is_empty()
                               ? commit_params.original_url
                               : common_params.url;
  navigation_params->http_method = WebString::FromASCII(
      !commit_params.original_method.empty() ? commit_params.original_method
                                             : common_params.method);

  if (common_params.referrer->url.is_valid()) {
    WebString referrer = WebSecurityPolicy::GenerateReferrerHeader(
        common_params.referrer->policy, common_params.url,
        WebString::FromUTF8(common_params.referrer->url.spec()));
    navigation_params->referrer = referrer;
    navigation_params->referrer_policy = common_params.referrer->policy;
  }
  if (common_params.referrer->policy !=
      network::mojom::ReferrerPolicy::kDefault) {
    navigation_params->referrer_policy = common_params.referrer->policy;
  }

  if (common_params.post_data) {
    navigation_params->http_body =
        blink::GetWebHTTPBodyForRequestBody(*common_params.post_data);
    if (!commit_params.post_content_type.empty()) {
      navigation_params->http_content_type =
          WebString::FromASCII(commit_params.post_content_type);
    }
  }

  // Set the request initiator origin, which is supplied by the browser
  // process. It is present in cases such as navigating a frame in a different
  // process, which is routed through `blink::RemoteFrame` and the origin is
  // required to correctly compute the effective origin in which the
  // navigation will commit.
  if (common_params.initiator_origin) {
    navigation_params->requestor_origin =
        common_params.initiator_origin.value();
  }

  navigation_params->initiator_origin_trial_features = {
      common_params.initiator_origin_trial_features.begin(),
      common_params.initiator_origin_trial_features.end()};

  navigation_params->was_discarded = commit_params.was_discarded;
  navigation_params->document_ukm_source_id =
      commit_params.document_ukm_source_id;

  navigation_params->prefetched_signed_exchanges = base::ToVector(
      commit_params.prefetched_signed_exchanges, [](const auto& exchange) {
        blink::WebURLResponse web_response = blink::WebURLResponse::Create(
            exchange->inner_url, *exchange->inner_response,
            false /* report_security_info*/, -1 /* request_id */);
        return std::make_unique<
            blink::WebNavigationParams::PrefetchedSignedExchange>(
            exchange->outer_url,
            WebString::FromLatin1(
                signed_exchange_utils::CreateHeaderIntegrityHashString(
                    exchange->header_integrity)),
            exchange->inner_url, web_response,
            std::move(exchange->loader_factory_handle));
      });

  navigation_params->had_transient_user_activation =
      common_params.has_user_gesture;

  navigation_params->force_enabled_origin_trials = base::ToVector(
      commit_params.force_enabled_origin_trials, &WebString::FromASCII);

  navigation_params->early_hints_preloaded_resources = base::ToVector(
      commit_params.early_hints_preloaded_resources, blink::ToWebURL);

  // Pass on the `initiator_base_url` sent via the common_params for srcdoc and
  // about:blank documents. This will be picked up in DocumentLoader.
  // Note: It's possible for initiator_base_url to be empty if this is an
  // error srcdoc page. See test
  // NavigationRequestBrowserTest.OriginForSrcdocErrorPageInSubframe.
  if (common_params.initiator_base_url) {
    CHECK(common_params.url.IsAboutSrcdoc() ||
          common_params.url.IsAboutBlank());
    navigation_params->fallback_base_url =
        common_params.initiator_base_url.value();
  } else {
    navigation_params->fallback_base_url = WebURL();
  }
}

blink::mojom::CommonNavigationParamsPtr MakeCommonNavigationParams(
    const WebSecurityOrigin& current_origin,
    std::unique_ptr<blink::WebNavigationInfo> info,
    int load_flags,
    bool has_download_sandbox_flag,
    bool from_ad,
    bool is_history_navigation_in_new_child_frame,
    network::mojom::RequestDestination request_destination) {
  // A valid RequestorOrigin is always expected to be present.
  DCHECK(!info->url_request.RequestorOrigin().IsNull());

  blink::mojom::ReferrerPtr referrer = blink::mojom::Referrer::New(
      blink::WebStringToGURL(info->url_request.ReferrerString()),
      info->url_request.GetReferrerPolicy());

  // No history-navigation is expected to happen.
  DCHECK(info->navigation_type != blink::kWebNavigationTypeBackForward);

  // Determine the navigation type. No same-document navigation is expected
  // because it is loaded immediately by the FrameLoader.
  blink::mojom::NavigationType navigation_type =
      blink::mojom::NavigationType::DIFFERENT_DOCUMENT;
  if (info->navigation_type == blink::kWebNavigationTypeReload) {
    if (load_flags & net::LOAD_BYPASS_CACHE)
      navigation_type = blink::mojom::NavigationType::RELOAD_BYPASSING_CACHE;
    else
      navigation_type = blink::mojom::NavigationType::RELOAD;
  }

  auto source_location = network::mojom::SourceLocation::New(
      info->source_location.url.Latin1(), info->source_location.line_number,
      info->source_location.column_number);

  const blink::WebURLRequestExtraData* url_request_extra_data =
      static_cast<blink::WebURLRequestExtraData*>(
          info->url_request.GetURLRequestExtraData().get());
  DCHECK(url_request_extra_data);

  blink::NavigationDownloadPolicy download_policy;
  download_policy.ApplyDownloadFramePolicy(
      info->is_opener_navigation, info->url_request.HasUserGesture(),
      info->url_request.RequestorOrigin().CanAccess(current_origin),
      has_download_sandbox_flag, from_ad);

  std::optional<GURL> initiator_base_url;
  GURL requestor_base_url(info->requestor_base_url);
  // Make sure the url length doesn't exceed the limit enforced by Mojo when
  // it's sent to the browser process.
  if (requestor_base_url.is_valid() &&
      requestor_base_url.possibly_invalid_spec().length() <=
          url::kMaxURLChars) {
    initiator_base_url = requestor_base_url;
  }
  return blink::mojom::CommonNavigationParams::New(
      info->url_request.Url(), info->url_request.RequestorOrigin(),
      initiator_base_url, std::move(referrer),
      url_request_extra_data->transition_type(), navigation_type,
      download_policy,
      info->frame_load_type == WebFrameLoadType::kReplaceCurrentItem, GURL(),
      info->actual_navigation_start,
      /*navigation_start=*/base::TimeTicks::Now(),
      info->url_request.HttpMethod().Latin1(),
      blink::GetRequestBodyForWebURLRequest(info->url_request),
      std::move(source_location), false /* started_from_context_menu */,
      info->url_request.HasUserGesture(),
      info->url_request.HasTextFragmentToken(),
      info->should_check_main_world_content_security_policy,
      info->initiator_origin_trial_features, info->href_translate.Latin1(),
      is_history_navigation_in_new_child_frame, info->input_start,
      request_destination);
}

WebFrameLoadType NavigationTypeToLoadType(
    blink::mojom::NavigationType navigation_type,
    bool should_replace_current_entry) {
  switch (navigation_type) {
    case blink::mojom::NavigationType::RELOAD:
      return WebFrameLoadType::kReload;

    case blink::mojom::NavigationType::RELOAD_BYPASSING_CACHE:
      return WebFrameLoadType::kReloadBypassingCache;

    case blink::mojom::NavigationType::HISTORY_SAME_DOCUMENT:
    case blink::mojom::NavigationType::HISTORY_DIFFERENT_DOCUMENT:
      return WebFrameLoadType::kBackForward;

    case blink::mojom::NavigationType::RESTORE:
    case blink::mojom::NavigationType::RESTORE_WITH_POST:
      return WebFrameLoadType::kRestore;

    case blink::mojom::NavigationType::SAME_DOCUMENT:
    case blink::mojom::NavigationType::DIFFERENT_DOCUMENT:
      return should_replace_current_entry
                 ? WebFrameLoadType::kReplaceCurrentItem
                 : WebFrameLoadType::kStandard;

    default:
      NOTREACHED();
  }
}

RenderFrameImpl::CreateRenderFrameImplFunction g_create_render_frame_impl =
    nullptr;

WebString ConvertRelativePathToHtmlAttribute(const base::FilePath& path) {
  DCHECK(!path.IsAbsolute());
  return WebString::FromUTF8(
      std::string("./") +
      path.NormalizePathSeparatorsTo(FILE_PATH_LITERAL('/')).AsUTF8Unsafe());
}

class RenderFrameWebFrameSerializerClient
    : public blink::WebFrameSerializerClient {
 public:
  explicit RenderFrameWebFrameSerializerClient(
      mojo::PendingRemote<mojom::FrameHTMLSerializerHandler> handler_remote)
      : handler_remote_(std::move(handler_remote)) {}

  // WebFrameSerializerClient implementation:
  void DidSerializeDataForFrame(
      const std::vector<char>& data,
      WebFrameSerializerClient::FrameSerializationStatus status) override {
    DCHECK(handler_remote_.is_bound());
    handler_remote_->DidReceiveData(std::string(data.data(), data.size()));

    // Make sure to report Done() to the browser process when receiving the last
    // chunk of data, and reset the mojo remote so that the DCHECK above ensures
    // this method won't be called anymore after this point.
    if (status == WebFrameSerializerClient::kCurrentFrameIsFinished) {
      handler_remote_->Done();
      handler_remote_.reset();
    }
  }

 private:
  mojo::Remote<mojom::FrameHTMLSerializerHandler> handler_remote_;
};

// Implementation of WebFrameSerializer::LinkRewritingDelegate that responds
// based on the payload of mojom::Frame::GetSerializedHtmlWithLocalLinks().
class LinkRewritingDelegate : public WebFrameSerializer::LinkRewritingDelegate {
 public:
  LinkRewritingDelegate(
      const base::flat_map<GURL, base::FilePath>& url_to_local_path,
      const base::flat_map<blink::FrameToken, base::FilePath>&
          frame_token_to_local_path)
      : url_to_local_path_(url_to_local_path),
        frame_token_to_local_path_(frame_token_to_local_path) {}

  bool RewriteFrameSource(WebFrame* frame, WebString* rewritten_link) override {
    const blink::FrameToken frame_token = frame->GetFrameToken();
    auto it = frame_token_to_local_path_->find(frame_token);
    if (it == frame_token_to_local_path_->end()) {
      return false;  // This can happen because of https://crbug.com/541354.
    }

    const base::FilePath& local_path = it->second;
    *rewritten_link = ConvertRelativePathToHtmlAttribute(local_path);
    return true;
  }

  bool RewriteLink(const WebURL& url, WebString* rewritten_link) override {
    auto it = url_to_local_path_->find(GURL(url));
    if (it == url_to_local_path_->end()) {
      return false;
    }

    const base::FilePath& local_path = it->second;
    *rewritten_link = ConvertRelativePathToHtmlAttribute(local_path);
    return true;
  }

 private:
  const raw_ref<const base::flat_map<GURL, base::FilePath>> url_to_local_path_;
  const raw_ref<const base::flat_map<blink::FrameToken, base::FilePath>>
      frame_token_to_local_path_;
};

bool IsHttpPost(const blink::WebURLRequest& request) {
  return request.HttpMethod().Utf8() == "POST";
}

// Delegate responsible for determining the handle writing implementation by
// instantiating an MHTMLHandleWriter on the heap respective to the passed in
// MHTMLSerializationParams. This transfers ownership of the handle to the
// new MHTMLHandleWriter.
class MHTMLHandleWriterDelegate {
 public:
  MHTMLHandleWriterDelegate(
      const mojom::SerializeAsMHTMLParams& params,
      MHTMLHandleWriter::MHTMLWriteCompleteCallback callback,
      scoped_refptr<base::TaskRunner> main_thread_task_runner) {
    // Handle must be instantiated.
    DCHECK(params.output_handle);

    if (params.output_handle->is_file_handle()) {
      handle_ = std::make_unique<MHTMLFileHandleWriter>(
          std::move(main_thread_task_runner), std::move(callback),
          std::move(params.output_handle->get_file_handle()));
    } else {
      handle_ = std::make_unique<MHTMLProducerHandleWriter>(
          std::move(main_thread_task_runner), std::move(callback),
          std::move(params.output_handle->get_producer_handle()));
    }
  }

  MHTMLHandleWriterDelegate(const MHTMLHandleWriterDelegate&) = delete;
  MHTMLHandleWriterDelegate& operator=(const MHTMLHandleWriterDelegate&) =
      delete;

  void WriteContents(std::vector<WebThreadSafeData> mhtml_contents) {
    // MHTMLHandleWriter::WriteContents calls MHTMLHandleWriter::Finish
    // eventually.
    base::ThreadPool::PostTask(
        FROM_HERE, {base::MayBlock()},
        base::BindOnce(&MHTMLHandleWriter::WriteContents, std::move(handle_),
                       std::move(mhtml_contents)));
  }

  // Within the context of the delegate, only for premature write finish.
  void Finish(mojom::MhtmlSaveStatus save_status) {
    base::ThreadPool::PostTask(FROM_HERE, {base::MayBlock()},
                               base::BindOnce(&MHTMLHandleWriter::Finish,
                                              std::move(handle_), save_status));
  }

 private:
  std::unique_ptr<MHTMLHandleWriter> handle_;
};

mojo::PendingRemote<blink::mojom::BlobURLToken> CloneBlobURLToken(
    blink::CrossVariantMojoRemote<blink::mojom::BlobURLTokenInterfaceBase>&
        blob_url_token) {
  if (!blob_url_token)
    return mojo::NullRemote();
  mojo::PendingRemote<blink::mojom::BlobURLToken> cloned_token;
  mojo::Remote<blink::mojom::BlobURLToken> token(std::move(blob_url_token));
  token->Clone(cloned_token.InitWithNewPipeAndPassReceiver());
  blob_url_token = token.Unbind();
  return cloned_token;
}

// Creates a fully functional DocumentState in the case where we do not have
// navigation parameters available.
std::unique_ptr<DocumentState> BuildDocumentState() {
  std::unique_ptr<DocumentState> document_state =
      std::make_unique<DocumentState>();
  document_state->set_navigation_state(
      NavigationState::CreateForSynchronousCommit());
  return document_state;
}

// Creates a fully functional DocumentState in the case where we have
// navigation parameters available in the RenderFrameImpl.
std::unique_ptr<DocumentState> BuildDocumentStateFromParams(
    const blink::mojom::CommonNavigationParams& common_params,
    const blink::mojom::CommitNavigationParams& commit_params,
    mojom::NavigationClient::CommitNavigationCallback commit_callback,
    std::unique_ptr<NavigationClient> navigation_client,
    int request_id,
    bool was_initiated_in_this_frame) {
  std::unique_ptr<DocumentState> document_state(new DocumentState());

  DCHECK(!common_params.navigation_start.is_null());
  DCHECK(!common_params.url.SchemeIs(url::kJavaScriptScheme));

  document_state->set_is_overriding_user_agent(
      commit_params.is_overriding_user_agent);
  document_state->set_request_id(request_id);

  // If this is a loadDataWithBaseURL request, save the commit URL so that we
  // can send a DidCommit message with the URL that was originally sent by the
  // browser in CommonNavigationParams (See MaybeGetOverriddenURL()).
  document_state->set_was_load_data_with_base_url_request(
      commit_params.is_load_data_with_base_url);
  if (commit_params.is_load_data_with_base_url)
    document_state->set_data_url(common_params.url);

  document_state->set_navigation_state(
      NavigationState::CreateForCrossDocumentCommit(
          common_params.Clone(), commit_params.Clone(),
          std::move(commit_callback), std::move(navigation_client),
          was_initiated_in_this_frame));
  return document_state;
}

std::optional<WebURL> ApplyFilePathAlias(const WebURL& target) {
  const base::CommandLine::StringType file_url_path_alias =
      base::CommandLine::ForCurrentProcess()->GetSwitchValueNative(
          switches::kFileUrlPathAlias);
  if (file_url_path_alias.empty()) {
    return std::nullopt;
  }

  const auto alias_mapping =
      base::SplitString(file_url_path_alias, FILE_PATH_LITERAL("="),
                        base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  if (alias_mapping.size() != 2) {
    LOG(ERROR) << "Invalid file path alias format.";
    return std::nullopt;
  }

#if BUILDFLAG(IS_WIN)
  std::wstring path = base::UTF16ToWide(target.GetString().Utf16());
  const std::wstring file_prefix =
      base::ASCIIToWide(url::kFileScheme) +
      base::ASCIIToWide(url::kStandardSchemeSeparator);
#else
  std::string path = target.GetString().Utf8();
  const std::string file_prefix =
      std::string(url::kFileScheme) + url::kStandardSchemeSeparator;
#endif
  if (!base::StartsWith(path, file_prefix + alias_mapping[0],
                        base::CompareCase::SENSITIVE)) {
    return std::nullopt;
  }

  base::ReplaceFirstSubstringAfterOffset(&path, 0, alias_mapping[0],
                                         alias_mapping[1]);
#if BUILDFLAG(IS_WIN)
  return blink::WebURL(GURL(base::WideToUTF8(path)));
#else
  return blink::WebURL(GURL(path));
#endif
}

// Packs all navigation timings sent by the browser to a blink understandable
// format, blink::WebNavigationTimings.
blink::WebNavigationTimings BuildNavigationTimings(
    base::TimeTicks navigation_start,
    const blink::mojom::NavigationTiming& browser_navigation_timings,
    base::TimeTicks input_start) {
  blink::WebNavigationTimings renderer_navigation_timings;

  // Sanitizes the navigation_start timestamp for browser-initiated navigations,
  // where the browser possibly has a better notion of start time than the
  // renderer. In the case of cross-process navigations, this carries over the
  // time of finishing the onbeforeunload handler of the previous page.
  // TimeTicks is sometimes not monotonic across processes, and because
  // |browser_navigation_start| is likely before this process existed,
  // InterProcessTimeTicksConverter won't help. The timestamp is sanitized by
  // clamping it to now.
  DCHECK(!navigation_start.is_null());
  renderer_navigation_timings.navigation_start =
      std::min(navigation_start, base::TimeTicks::Now());

  renderer_navigation_timings.redirect_start =
      browser_navigation_timings.redirect_start;
  renderer_navigation_timings.redirect_end =
      browser_navigation_timings.redirect_end;
  renderer_navigation_timings.fetch_start =
      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;

  renderer_navigation_timings.system_entropy_at_navigation_start =
      browser_navigation_timings.system_entropy_at_navigation_start;

  return renderer_navigation_timings;
}

WebHistoryItem NavigationApiHistoryEntryPtrToWebHistoryItem(
    const blink::mojom::NavigationApiHistoryEntry& entry) {
  return WebHistoryItem(
      WebString::FromUTF16(entry.url), WebString::FromUTF16(entry.key),
      WebString::FromUTF16(entry.id), entry.item_sequence_number,
      entry.document_sequence_number, WebString::FromUTF16(entry.state));
}

// Fills navigation data sent by the browser to a blink understandable
// format, blink::WebNavigationParams.
void FillMiscNavigationParams(
    const blink::mojom::CommonNavigationParams& common_params,
    blink::mojom::CommitNavigationParams& commit_params,
    blink::WebNavigationParams* navigation_params) {
  navigation_params->navigation_timings = BuildNavigationTimings(
      common_params.navigation_start, *commit_params.navigation_timing,
      common_params.input_start);
  if (!commit_params.redirect_infos.empty()) {
    navigation_params->navigation_timings.critical_ch_restart =
        commit_params.redirect_infos.back().critical_ch_restart_time;
  }

  navigation_params->is_user_activated =
      commit_params.was_activated == blink::mojom::WasActivatedOption::kYes;

  navigation_params->has_text_fragment_token =
      common_params.text_fragment_token;

  navigation_params->is_browser_initiated = commit_params.is_browser_initiated;

  navigation_params->is_cross_site_cross_browsing_context_group =
      commit_params.is_cross_site_cross_browsing_context_group;

  navigation_params->should_have_sticky_user_activation =
      commit_params.should_have_sticky_user_activation;

#if BUILDFLAG(IS_ANDROID)
  // Only android webview uses this.
  navigation_params->grant_load_local_resources =
      commit_params.can_load_local_resources;
#else
  DCHECK(!commit_params.can_load_local_resources);
#endif

  navigation_params->origin_to_commit = commit_params.origin_to_commit;
  navigation_params->storage_key = std::move(commit_params.storage_key);

  navigation_params->frame_policy = commit_params.frame_policy;

  if (common_params.navigation_type == blink::mojom::NavigationType::RESTORE) {
    // We're doing a load of a page that was restored from the last session.
    // By default this prefers the cache over loading
    // (LOAD_SKIP_CACHE_VALIDATION) which can result in stale data for pages
    // that are set to expire. We explicitly override that by setting the
    // policy here so that as necessary we load from the network.
    //
    // TODO(davidben): Remove this in favor of passing a cache policy to the
    // loadHistoryItem call in OnNavigate. That requires not overloading
    // UseProtocolCachePolicy to mean both "normal load" and "determine cache
    // policy based on load type, etc".
    navigation_params->force_fetch_cache_mode =
        blink::mojom::FetchCacheMode::kDefault;
  }

  navigation_params->origin_agent_cluster = commit_params.origin_agent_cluster;
  navigation_params->origin_agent_cluster_left_as_default =
      commit_params.origin_agent_cluster_left_as_default;

  navigation_params->reduced_accept_language =
      WebString::FromASCII(commit_params.reduced_accept_language);
  navigation_params->enabled_client_hints.reserve(
      commit_params.enabled_client_hints.size());
  for (auto enabled_hint : commit_params.enabled_client_hints)
    navigation_params->enabled_client_hints.emplace_back(enabled_hint);

  if (commit_params.http_response_code != -1)
    navigation_params->http_status_code = commit_params.http_response_code;

  // Copy the modified runtime features from `commit_params` to send to the
  // Blink renderer class WebLocalFrameImpl.
  navigation_params->modified_runtime_features =
      commit_params.modified_runtime_features;

  // Populate the arrays of non-current entries for the window.navigation API.
  auto& entry_arrays = commit_params.navigation_api_history_entry_arrays;
  navigation_params->navigation_api_back_entries.reserve(
      entry_arrays->back_entries.size());
  for (const auto& entry : entry_arrays->back_entries) {
    navigation_params->navigation_api_back_entries.emplace_back(
        NavigationApiHistoryEntryPtrToWebHistoryItem(*entry));
  }
  navigation_params->navigation_api_forward_entries.reserve(
      entry_arrays->forward_entries.size());
  for (const auto& entry : entry_arrays->forward_entries) {
    navigation_params->navigation_api_forward_entries.emplace_back(
        NavigationApiHistoryEntryPtrToWebHistoryItem(*entry));
  }
  if (entry_arrays->previous_entry) {
    navigation_params->navigation_api_previous_entry =
        NavigationApiHistoryEntryPtrToWebHistoryItem(
            *entry_arrays->previous_entry);
  }

  if (commit_params.fenced_frame_properties) {
    navigation_params->fenced_frame_properties =
        commit_params.fenced_frame_properties;

    if (commit_params.fenced_frame_properties->nested_urn_config_pairs() &&
        commit_params.fenced_frame_properties->nested_urn_config_pairs()
            ->potentially_opaque_value.has_value()) {
      const auto& nested_urn_config_pairs_value =
          commit_params.fenced_frame_properties->nested_urn_config_pairs()
              ->potentially_opaque_value.value();
      DCHECK_EQ(blink::MaxAdAuctionAdComponents(),
                nested_urn_config_pairs_value.size());
      navigation_params->ad_auction_components.emplace();
      for (const auto& nested_urn_config_pair : nested_urn_config_pairs_value) {
        const GURL& urn = nested_urn_config_pair.first;
        DCHECK(urn.SchemeIs(url::kUrnScheme));
        navigation_params->ad_auction_components->push_back(blink::WebURL(urn));
      }
    }
  }

  navigation_params->ancestor_or_self_has_cspee =
      commit_params.ancestor_or_self_has_cspee;

  navigation_params->browsing_context_group_token =
      commit_params.browsing_context_group_token;

  navigation_params->content_settings =
      std::move(commit_params.content_settings);

  if (commit_params.cookie_deprecation_label.has_value()) {
    navigation_params->cookie_deprecation_label =
        WebString::FromASCII(*commit_params.cookie_deprecation_label);
  }
  navigation_params->initial_permission_statuses =
      std::move(commit_params.initial_permission_statuses);

  navigation_params->force_new_document_sequence_number =
      commit_params.force_new_document_sequence_number;
}

std::string GetUniqueNameOfWebFrame(WebFrame* web_frame) {
  if (web_frame->IsWebLocalFrame())
    return RenderFrameImpl::FromWebFrame(web_frame)->unique_name();
  return web_frame->ToWebRemoteFrame()->UniqueName().Utf8();
}

perfetto::protos::pbzero::FrameDeleteIntention FrameDeleteIntentionToProto(
    mojom::FrameDeleteIntention intent) {
  using ProtoLevel = perfetto::protos::pbzero::FrameDeleteIntention;
  switch (intent) {
    case mojom::FrameDeleteIntention::kNotMainFrame:
      return ProtoLevel::FRAME_DELETE_INTENTION_NOT_MAIN_FRAME;
    case mojom::FrameDeleteIntention::kSpeculativeMainFrameForShutdown:
      return ProtoLevel::
          FRAME_DELETE_INTENTION_SPECULATIVE_MAIN_FRAME_FOR_SHUTDOWN;
    case mojom::FrameDeleteIntention::
        kSpeculativeMainFrameForNavigationCancelled:
      return ProtoLevel::
          FRAME_DELETE_INTENTION_SPECULATIVE_MAIN_FRAME_FOR_NAVIGATION_CANCELLED;
  }
  // All cases should've been handled by the switch case above.
  NOTREACHED();
}

void CallClientDeferMediaLoad(base::WeakPtr<RenderFrameImpl> frame,
                              bool has_played_media_before,
                              base::OnceClosure closure) {
  if (!frame)
    return;
  GetContentClient()->renderer()->DeferMediaLoad(
      frame.get(), has_played_media_before, std::move(closure));
}

void LogCommitHistograms(base::TimeTicks commit_sent,
                         bool is_main_frame,
                         const GURL& new_page_url) {
  if (!base::TimeTicks::IsConsistentAcrossProcesses())
    return;

  const char* frame_type = is_main_frame ? "MainFrame" : "Subframe";
  auto now = base::TimeTicks::Now();
  base::UmaHistogramTimes(
      base::StrCat({"Navigation.RendererCommitDelay.", frame_type}),
      now - commit_sent);
  if (auto* task = base::TaskAnnotator::CurrentTaskForThread()) {
    base::UmaHistogramTimes(
        base::StrCat({"Navigation.RendererCommitQueueTime.", frame_type}),
        now - task->queue_time);
  }

  // Some tests don't set the render thread.
  if (!RenderThreadImpl::current())
    return;

  base::TimeTicks run_loop_start_time =
      RenderThreadImpl::current()->run_loop_start_time();
  // If the commit was sent before the run loop was started for this process,
  // the navigation was likely delayed while waiting for the process to start.
  if (commit_sent < run_loop_start_time) {
    base::UmaHistogramTimes(
        base::StrCat({"Navigation.RendererCommitProcessWaitTime.", frame_type}),
        run_loop_start_time - commit_sent);
  }

  // We want to record the following metric just one time per process.
  static bool is_first_commit = true;
  if (is_first_commit) {
    is_first_commit = false;
    if (run_loop_start_time <= now && new_page_url.is_valid() &&
        new_page_url.SchemeIsHTTPOrHTTPS()) {
      const char* const name =
          is_main_frame
              ? "Navigation.RendererRunLoopStartToFirstCommitNavigation2."
                "MainFrame"
              : "Navigation.RendererRunLoopStartToFirstCommitNavigation2."
                "Subframe";
      const auto trace_id = perfetto::NamedTrack(
          perfetto::StaticString(name),
          reinterpret_cast<uintptr_t>(RenderThreadImpl::current()));
      TRACE_EVENT_BEGIN("navigation", perfetto::StaticString(name), trace_id,
                        run_loop_start_time, "url", new_page_url);
      TRACE_EVENT_END("navigation", trace_id, now);
      base::UmaHistogramLongTimes(name, now - run_loop_start_time);
    }
  }
}

content::mojom::WindowContainerType WindowFeaturesToContainerType(
    const blink::WebWindowFeatures& window_features) {
  if (window_features.background) {
    if (window_features.persistent)
      return content::mojom::WindowContainerType::PERSISTENT;
    else
      return content::mojom::WindowContainerType::BACKGROUND;
  } else {
    return content::mojom::WindowContainerType::NORMAL;
  }
}

WindowOpenDisposition NavigationPolicyToDisposition(
    WebNavigationPolicy policy) {
  switch (policy) {
    case blink::kWebNavigationPolicyDownload:
      return WindowOpenDisposition::SAVE_TO_DISK;
    case blink::kWebNavigationPolicyCurrentTab:
      return WindowOpenDisposition::CURRENT_TAB;
    case blink::kWebNavigationPolicyNewBackgroundTab:
      return WindowOpenDisposition::NEW_BACKGROUND_TAB;
    case blink::kWebNavigationPolicyNewForegroundTab:
      return WindowOpenDisposition::NEW_FOREGROUND_TAB;
    case blink::kWebNavigationPolicyNewWindow:
      return WindowOpenDisposition::NEW_WINDOW;
    case blink::kWebNavigationPolicyNewPopup:
      return WindowOpenDisposition::NEW_POPUP;
    case blink::kWebNavigationPolicyPictureInPicture:
      return WindowOpenDisposition::NEW_PICTURE_IN_PICTURE;
  }
  NOTREACHED() << "Unexpected WebNavigationPolicy";
}

bool ShouldNotifySubresourceResponseStarted(
    const blink::RendererPreferences& pref) {
  if (!base::FeatureList::IsEnabled(
          features::kReduceSubresourceResponseStartedIPC)) {
    return true;
  }
  return pref.send_subresource_notification;
}

// Initialize the WebFrameWidget with compositing. Only local root frames
// create a widget.
// `previous_widget` indicates whether the compositor for the frame which
// is being replaced by this frame should be used instead of creating a new
// compositor instance.
void InitializeFrameWidgetForFrame(
    WebLocalFrame& frame,
    blink::WebFrameWidget* previous_widget,
    mojom::CreateFrameWidgetParamsPtr widget_params,
    const bool is_for_nested_main_frame) {
  CHECK(widget_params);

  const bool is_main_frame = !frame.Parent();
  CHECK(is_main_frame || !is_for_nested_main_frame);

  const bool is_for_scalable_page =
      is_main_frame && !frame.View()->IsFencedFrameRoot();

  const auto frame_sink_id =
      previous_widget ? previous_widget->GetFrameSinkId()
                      : viz::FrameSinkId(RenderThread::Get()->GetClientId(),
                                         widget_params->routing_id);
  auto* web_frame_widget = frame.InitializeFrameWidget(
      std::move(widget_params->frame_widget_host),
      std::move(widget_params->frame_widget),
      std::move(widget_params->widget_host), std::move(widget_params->widget),
      frame_sink_id, is_for_nested_main_frame, is_for_scalable_page,
      /*hidden=*/true);

  if (previous_widget) {
    web_frame_widget->InitializeCompositingFromPreviousWidget(
        widget_params->visual_properties.screen_infos,
        /*settings=*/nullptr, *previous_widget);
  } else {
    web_frame_widget->InitializeCompositing(
        widget_params->visual_properties.screen_infos,
        /*settings=*/nullptr);
  }

  // The WebFrameWidget should start with valid VisualProperties, including a
  // non-zero size. While WebFrameWidget would not normally receive IPCs and
  // thus would not get VisualProperty updates while the frame is provisional,
  // we need at least one update to them in order to meet expectations in the
  // renderer, and that update comes as part of the CreateFrame message.
  // TODO(crbug.com/40387047): This could become part of WebFrameWidget Init.
  web_frame_widget->ApplyVisualProperties(widget_params->visual_properties);
}

}  // namespace

// Implementation of WebFrameSerializer::MHTMLPartsGenerationDelegate that
// 1. Bases shouldSkipResource and getContentID responses on contents of
//    SerializeAsMHTMLParams.
// 2. Stores digests of urls of serialized resources (i.e. urls reported via
//    shouldSkipResource) into |serialized_resources_uri_digests| passed
//    to the constructor.
class MHTMLPartsGenerationDelegateImpl final
    : public WebFrameSerializer::MHTMLPartsGenerationDelegate {
 public:
  explicit MHTMLPartsGenerationDelegateImpl(
      mojom::SerializeAsMHTMLParamsPtr params)
      : params_(std::move(params)) {
    // Digests must be sorted for binary search.
    DCHECK(std::is_sorted(params_->digests_of_uris_to_skip.begin(),
                          params_->digests_of_uris_to_skip.end()));
    // URLs are not duplicated.
    DCHECK(std::ranges::adjacent_find(params_->digests_of_uris_to_skip) ==
           params_->digests_of_uris_to_skip.end());
  }

  MHTMLPartsGenerationDelegateImpl(const MHTMLPartsGenerationDelegateImpl&) =
      delete;
  MHTMLPartsGenerationDelegateImpl& operator=(
      const MHTMLPartsGenerationDelegateImpl&) = delete;

  bool ShouldSkipResource(const WebURL& url) override {
    std::string digest =
        crypto::SHA256HashString(params_->salt + GURL(url).spec());

    // Skip if the |url| already covered by serialization of an *earlier* frame.
    if (std::binary_search(params_->digests_of_uris_to_skip.begin(),
                           params_->digests_of_uris_to_skip.end(), digest)) {
      return true;
    }

    // Let's record |url| as being serialized for the *current* frame.
    auto pair = serialized_resources_uri_digests_.insert(digest);
    bool insertion_took_place = pair.second;
    DCHECK(insertion_took_place);  // Blink should dedupe within a frame.

    return false;
  }

  bool UseBinaryEncoding() override { return params_->mhtml_binary_encoding; }

  bool RemovePopupOverlay() override {
    return params_->mhtml_popup_overlay_removal;
  }

  std::unordered_set<std::string> TakeSerializedResourcesUriDigests() {
    return std::move(serialized_resources_uri_digests_);
  }
  mojom::SerializeAsMHTMLParamsPtr TakeParams() { return std::move(params_); }

 private:
  std::vector<std::string> digests_of_uris_to_skip_;
  mojom::SerializeAsMHTMLParamsPtr params_;
  std::unordered_set<std::string> serialized_resources_uri_digests_;
};

RenderFrameImpl::AssertNavigationCommits::AssertNavigationCommits(
    RenderFrameImpl* frame)
    : AssertNavigationCommits(frame, false) {}

RenderFrameImpl::AssertNavigationCommits::AssertNavigationCommits(
    RenderFrameImpl* frame,
    MayReplaceInitialEmptyDocumentTag)
    : AssertNavigationCommits(frame, true) {}

RenderFrameImpl::AssertNavigationCommits::~AssertNavigationCommits() {
  // Frame might have been synchronously detached when dispatching JS events.
  if (frame_) {
    CHECK_EQ(NavigationCommitState::kDidCommit,
             frame_->navigation_commit_state_);
    frame_->navigation_commit_state_ = NavigationCommitState::kNone;
  }
}

RenderFrameImpl::AssertNavigationCommits::AssertNavigationCommits(
    RenderFrameImpl* frame,
    bool allow_transition_from_initial_empty_document)
    : frame_(frame->weak_factory_.GetWeakPtr()) {
  if (NavigationCommitState::kNone != frame->navigation_commit_state_) {
    CHECK(allow_transition_from_initial_empty_document);
    CHECK_EQ(NavigationCommitState::kInitialEmptyDocument,
             frame->navigation_commit_state_);
  }
  frame->navigation_commit_state_ = NavigationCommitState::kWillCommit;
}

// This class uses existing WebNavigationBodyLoader to read the whole response
// body into in-memory buffer, and then creates another body loader with static
// data so that we can parse mhtml archive synchronously. This is a workaround
// for the fact that we need the whole archive to determine the document's mime
// type and construct a right document instance.
class RenderFrameImpl::MHTMLBodyLoaderClient
    : public blink::WebNavigationBodyLoader::Client {
 public:
  // Once the body is read, fills |navigation_params| with the new body loader
  // and calls |done_callbcak|.
  MHTMLBodyLoaderClient(
      RenderFrameImpl* frame,
      std::unique_ptr<blink::WebNavigationParams> navigation_params,
      base::OnceCallback<void(std::unique_ptr<blink::WebNavigationParams>)>
          done_callback)
      : frame_(frame),
        navigation_params_(std::move(navigation_params)),
        body_loader_(std::move(navigation_params_->body_loader)),
        done_callback_(std::move(done_callback)) {
    body_loader_->StartLoadingBody(this);
  }

  MHTMLBodyLoaderClient(const MHTMLBodyLoaderClient&) = delete;
  MHTMLBodyLoaderClient& operator=(const MHTMLBodyLoaderClient&) = delete;

  ~MHTMLBodyLoaderClient() override {
    // MHTMLBodyLoaderClient is reset in several different places. Either:
    CHECK(
        // - the body load finished and the result is being committed, so
        //   |BodyLoadingFinished| (see below) should still be on the stack, or
        committing_ ||
        // - MHTMLBodyLoaderClient is abandoned, either because:
        //   - a new renderer-initiated navigation began, which explicitly
        //     detaches any existing MHTMLBodyLoaderClient
        //   - this renderer began the navigation and cancelled it with
        //     |AbortClientNavigation|, e.g. JS called window.stop(), which
        //     explicitly detaches any existing MHTMLBodyLoaderClient
        //   - the frame is detached and self-deleted, which also explicitly
        //     detaches any existing MHTMLBodyLoaderClient or,
        !frame_ ||
        //   - the browser requested a different navigation be committed in this
        //     frame, i.e. the navigation commit state should be |kWillCommit|
        NavigationCommitState::kWillCommit == frame_->navigation_commit_state_);
  }

  // Marks |this|'s pending load as abandoned. There are a number of reasons
  // this can happen; see the destructor for more information.
  void Detach() {
    // Note that the MHTMLBodyLoaderClient might be associated with a
    // provisional frame, so this does not assert that `frame_->in_frame_tree_`
    // is true.
    frame_ = nullptr;
  }

  // blink::WebNavigationBodyLoader::Client overrides:
  void BodyDataReceived(base::span<const char> data) override {
    data_.Append(base::as_bytes(data));
  }

  void BodyLoadingFinished(base::TimeTicks completion_time,
                           int64_t total_encoded_data_length,
                           int64_t total_encoded_body_length,
                           int64_t total_decoded_body_length,
                           const std::optional<WebURLError>& error) override {
    committing_ = true;
    AssertNavigationCommits assert_navigation_commits(frame_);
    if (!error.has_value()) {
      WebNavigationParams::FillBodyLoader(navigation_params_.get(), data_);
      // Clear |is_static_data| flag to avoid the special behavior it triggers,
      // e.g. skipping content disposition check. We want this load to be
      // regular, just like with an original body loader.
      navigation_params_->is_static_data = false;
    }
    std::move(done_callback_).Run(std::move(navigation_params_));
  }

 private:
  // |RenderFrameImpl| owns |this|, so |frame_| is guaranteed to outlive |this|.
  // Will be nulled if |Detach()| has been called.
  raw_ptr<RenderFrameImpl> frame_;
  bool committing_ = false;
  WebData data_;
  std::unique_ptr<blink::WebNavigationParams> navigation_params_;
  std::unique_ptr<blink::WebNavigationBodyLoader> body_loader_;
  base::OnceCallback<void(std::unique_ptr<blink::WebNavigationParams>)>
      done_callback_;
};

RenderFrameImpl::UniqueNameFrameAdapter::UniqueNameFrameAdapter(
    RenderFrameImpl* render_frame)
    : render_frame_(render_frame) {}

RenderFrameImpl::UniqueNameFrameAdapter::~UniqueNameFrameAdapter() {}

bool RenderFrameImpl::UniqueNameFrameAdapter::IsMainFrame() const {
  return render_frame_->IsMainFrame();
}

bool RenderFrameImpl::UniqueNameFrameAdapter::IsCandidateUnique(
    std::string_view name) const {
  // This method is currently O(N), where N = number of frames in the tree.
  DCHECK(!name.empty());

  for (blink::WebFrame* frame = GetWebFrame()->Top(); frame;
       frame = frame->TraverseNext()) {
    if (GetUniqueNameOfWebFrame(frame) == name)
      return false;
  }

  return true;
}

int RenderFrameImpl::UniqueNameFrameAdapter::GetSiblingCount() const {
  int sibling_count = 0;
  for (blink::WebFrame* frame = GetWebFrame()->Parent()->FirstChild(); frame;
       frame = frame->NextSibling()) {
    if (frame == GetWebFrame())
      continue;
    ++sibling_count;
  }
  return sibling_count;
}

int RenderFrameImpl::UniqueNameFrameAdapter::GetChildCount() const {
  int child_count = 0;
  for (blink::WebFrame* frame = GetWebFrame()->FirstChild(); frame;
       frame = frame->NextSibling()) {
    ++child_count;
  }
  return child_count;
}

std::vector<std::string>
RenderFrameImpl::UniqueNameFrameAdapter::CollectAncestorNames(
    BeginPoint begin_point,
    bool (*should_stop)(std::string_view)) const {
  std::vector<std::string> result;
  for (blink::WebFrame* frame = begin_point == BeginPoint::kParentFrame
                                    ? GetWebFrame()->Parent()
                                    : GetWebFrame();
       frame; frame = frame->Parent()) {
    result.push_back(GetUniqueNameOfWebFrame(frame));
    if (should_stop(result.back()))
      break;
  }
  return result;
}

std::vector<int> RenderFrameImpl::UniqueNameFrameAdapter::GetFramePosition(
    BeginPoint begin_point) const {
  std::vector<int> result;
  blink::WebFrame* parent = begin_point == BeginPoint::kParentFrame
                                ? GetWebFrame()->Parent()
                                : GetWebFrame();
  blink::WebFrame* child =
      begin_point == BeginPoint::kParentFrame ? GetWebFrame() : nullptr;
  while (parent) {
    int position_in_parent = 0;
    blink::WebFrame* sibling = parent->FirstChild();
    while (sibling != child) {
      sibling = sibling->NextSibling();
      ++position_in_parent;
    }
    result.push_back(position_in_parent);

    child = parent;
    parent = parent->Parent();
  }
  return result;
}

blink::WebLocalFrame* RenderFrameImpl::UniqueNameFrameAdapter::GetWebFrame()
    const {
  return render_frame_->frame_;
}

// static
RenderFrameImpl* RenderFrameImpl::Create(
    AgentSchedulingGroup& agent_scheduling_group,
    const blink::LocalFrameToken& frame_token,
    int32_t routing_id,
    mojo::PendingAssociatedReceiver<mojom::Frame> frame_receiver,
    mojo::PendingAssociatedRemote<blink::mojom::AssociatedInterfaceProvider>
        associated_interface_provider,
    const base::UnguessableToken& devtools_frame_token,
    bool is_for_nested_main_frame) {
  DCHECK(routing_id != IPC::mojom::kRoutingIdNone);
  CreateParams params(agent_scheduling_group, frame_token, routing_id,
                      std::move(frame_receiver),
                      std::move(associated_interface_provider),
                      devtools_frame_token, is_for_nested_main_frame);

  if (g_create_render_frame_impl)
    return g_create_render_frame_impl(std::move(params));
  else
    return new RenderFrameImpl(std::move(params));
}

// static
RenderFrameImpl* RenderFrameImpl::CreateMainFrame(
    AgentSchedulingGroup& agent_scheduling_group,
    blink::WebView* web_view,
    blink::WebFrame* opener,
    bool is_for_nested_main_frame,
    bool is_for_scalable_page,
    blink::mojom::FrameReplicationStatePtr replication_state,
    const base::UnguessableToken& devtools_frame_token,
    mojom::CreateLocalMainFrameParamsPtr params,
    const blink::WebURL& base_url) {
  // A main frame RenderFrame must have a RenderWidget.
  DCHECK_NE(IPC::mojom::kRoutingIdNone, params->widget_params->routing_id);

  RenderFrameImpl* render_frame = RenderFrameImpl::Create(
      agent_scheduling_group, params->frame_token, params->routing_id,
      std::move(params->frame),
      std::move(params->associated_interface_provider_remote),
      devtools_frame_token, is_for_nested_main_frame);

  WebLocalFrame* web_frame = WebLocalFrame::CreateMainFrame(
      web_view, render_frame, render_frame->blink_interface_registry_.get(),
      std::move(params->interface_broker), params->frame_token,
      params->document_token,
      ToWebPolicyContainer(std::move(params->policy_container)), opener,
      // This conversion is a little sad, as this often comes from a
      // WebString...
      WebString::FromUTF8(replication_state->name),
      replication_state->frame_policy.sandbox_flags, base_url);
  if (!params->is_on_initial_empty_document)
    render_frame->frame_->SetIsNotOnInitialEmptyDocument();

  CHECK(!params->widget_params->reuse_compositor);

  // Non-owning pointer that is self-referencing and destroyed by calling
  // Close(). The RenderViewImpl has a RenderWidget already, but not a
  // WebFrameWidget, which is now attached here.
  blink::WebFrameWidget* web_frame_widget = web_frame->InitializeFrameWidget(
      std::move(params->widget_params->frame_widget_host),
      std::move(params->widget_params->frame_widget),
      std::move(params->widget_params->widget_host),
      std::move(params->widget_params->widget),
      viz::FrameSinkId(RenderThread::Get()->GetClientId(),
                       params->widget_params->routing_id),
      is_for_nested_main_frame, is_for_scalable_page,
      /*hidden=*/true);
  web_frame_widget->InitializeCompositing(
      params->widget_params->visual_properties.screen_infos,
      /*settings=*/nullptr);

  // The WebFrame created here was already attached to the Page as its main
  // frame, and the WebFrameWidget has been initialized, so we can call
  // WebView's DidAttachLocalMainFrame().
  render_frame->GetWebView()->DidAttachLocalMainFrame();

  // The WebFrameWidget should start with valid VisualProperties, including a
  // non-zero size. While WebFrameWidget would not normally receive IPCs and
  // thus would not get VisualProperty updates while the frame is provisional,
  // we need at least one update to them in order to meet expectations in the
  // renderer, and that update comes as part of the CreateFrame message.
  // TODO(crbug.com/40387047): This could become part of WebFrameWidget Init.
  web_frame_widget->ApplyVisualProperties(
      params->widget_params->visual_properties);

  render_frame->in_frame_tree_ = true;
  render_frame->Initialize(nullptr);

  if (params->subresource_loader_factories
          ->IsTrackedChildPendingURLLoaderFactoryBundle()) {
    // In renderer-initiated creation of a new main frame (e.g. popup without
    // rel=noopener), `params->subresource_loader_factories` are inherited from
    // the creator frame (e.g. TrackedChildURLLoaderFactoryBundle will be
    // updated when the creator's bundle recovers from a NetworkService crash).
    // See also https://crbug.com/1194763#c5.
    render_frame->SetLoaderFactoryBundle(
        base::MakeRefCounted<blink::TrackedChildURLLoaderFactoryBundle>(
            base::WrapUnique(
                static_cast<blink::TrackedChildPendingURLLoaderFactoryBundle*>(
                    params->subresource_loader_factories.release()))));
  } else {
    // In browser-initiated creation of a new main frame (e.g. popup with
    // rel=noopener, or when creating a new tab) the Browser process provides
    // `params->subresource_loader_factories`.
    render_frame->SetLoaderFactoryBundle(
        render_frame->CreateLoaderFactoryBundle(
            std::move(params->subresource_loader_factories),
            /*subresource_overrides=*/std::nullopt,
            /*subresource_proxying_loader_factory=*/mojo::NullRemote(),
            /*keep_alive_loader_factory=*/mojo::NullRemote(),
            /*fetch_later_loader_factory=*/mojo::NullAssociatedRemote()));
  }

  return render_frame;
}

// static
void RenderFrameImpl::CreateFrame(
    AgentSchedulingGroup& agent_scheduling_group,
    const blink::LocalFrameToken& frame_token,
    int routing_id,
    mojo::PendingAssociatedReceiver<mojom::Frame> frame_receiver,
    mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
        browser_interface_broker,
    mojo::PendingAssociatedRemote<blink::mojom::AssociatedInterfaceProvider>
        associated_interface_provider,
    blink::WebView* web_view,
    base::optional_ref<const blink::FrameToken> previous_frame_token,
    base::optional_ref<const blink::FrameToken> opener_frame_token,
    base::optional_ref<const blink::FrameToken> parent_frame_token,
    base::optional_ref<const blink::FrameToken> previous_sibling_frame_token,
    const base::UnguessableToken& devtools_frame_token,
    const std::optional<base::UnguessableToken>& navigation_metrics_token,
    blink::mojom::TreeScopeType tree_scope_type,
    blink::mojom::FrameReplicationStatePtr replicated_state,
    mojom::CreateFrameWidgetParamsPtr widget_params,
    blink::mojom::FrameOwnerPropertiesPtr frame_owner_properties,
    bool is_on_initial_empty_document,
    const blink::DocumentToken& document_token,
    blink::mojom::PolicyContainerPtr policy_container,
    bool is_for_nested_main_frame) {
  base::ElapsedTimer timer;

  // TODO(danakj): Split this method into two pieces. The first block makes a
  // WebLocalFrame and collects the `blink::WebView` and RenderFrame for it. The
  // second block uses that to make a RenderWidget, if needed.
  RenderFrameImpl* render_frame = nullptr;
  blink::WebLocalFrame* web_frame = nullptr;
  if (!previous_frame_token) {
    // TODO(alexmos): This path is currently used only:
    // 1) When recreating a non-main RenderFrame after a crash.
    // 2) In tests that issue this IPC directly.
    // These two cases should be cleaned up to also pass a previous_frame_token,
    // which would allow removing this branch altogether.  See
    // https://crbug.com/756790.

    CHECK(parent_frame_token);
    WebFrame* parent_web_frame =
        WebFrame::FromFrameToken(parent_frame_token.value());

    // If the browser is sending a valid parent routing id, it should already
    // be created and registered.
    CHECK(parent_web_frame);
    CHECK(parent_web_frame->IsWebRemoteFrame());

    blink::WebFrame* previous_sibling_web_frame = nullptr;
    if (previous_sibling_frame_token) {
      previous_sibling_web_frame =
          blink::WebFrame::FromFrameToken(previous_sibling_frame_token.value());
    }

    // `web_view` would only be set by the function caller when creating a
    // provisional local main frame for a new WebView, which is handled in the
    // other branch of this if clause. Meanwhile, this branch handles subframe
    // creation case only, and we should use the parent's WebView in that case.
    CHECK(!web_view);
    web_view = parent_web_frame->View();

    // Create the RenderFrame and WebLocalFrame, linking the two.
    render_frame = RenderFrameImpl::Create(
        agent_scheduling_group, frame_token, routing_id,
        std::move(frame_receiver), std::move(associated_interface_provider),
        devtools_frame_token, is_for_nested_main_frame);
    render_frame->unique_name_helper_.set_propagated_name(
        replicated_state->unique_name);
    WebFrame* opener = nullptr;
    if (opener_frame_token)
      opener = WebFrame::FromFrameToken(opener_frame_token.value());
    web_frame = parent_web_frame->ToWebRemoteFrame()->CreateLocalChild(
        tree_scope_type, WebString::FromUTF8(replicated_state->name),
        replicated_state->frame_policy, render_frame,
        render_frame->blink_interface_registry_.get(),
        previous_sibling_web_frame,
        frame_owner_properties->To<blink::WebFrameOwnerProperties>(),
        frame_token, opener, document_token,
        std::move(browser_interface_broker),
        ToWebPolicyContainer(std::move(policy_container)));

    // The RenderFrame is created and inserted into the frame tree in the above
    // call to createLocalChild.
    render_frame->in_frame_tree_ = true;
  } else {
    WebFrame* previous_web_frame =
        WebFrame::FromFrameToken(previous_frame_token.value());
    // The previous frame could've been detached while the navigation was being
    // initiated in the browser process. Drop the navigation and don't create
    // the frame in that case.
    // See https://crbug.com/526304.
    if (!previous_web_frame)
      return;

    // This path is creating a local frame. It may or may not be a local root,
    // depending on whether the frame's parent is local or remote. It may also
    // be the main frame, which will be a provisional frame that can either
    // replace a remote main frame in the same WebView or a local main frame in
    // a different WebView.
    if (web_view) {
      // When a `web_view` is set by the caller, it must be for a provisional
      // main frame that will do a local frame swap. In this case, the WebView
      // must be different from the previous frame's WebView.
      CHECK(!previous_web_frame->Parent());
      CHECK_NE(web_view, previous_web_frame->View());
    } else {
      // When not set explicitly, reuse the previous frame's WebView.
      web_view = previous_web_frame->View();
    }
    render_frame = RenderFrameImpl::Create(
        agent_scheduling_group, frame_token, routing_id,
        std::move(frame_receiver), std::move(associated_interface_provider),
        devtools_frame_token, is_for_nested_main_frame);
    web_frame = blink::WebLocalFrame::CreateProvisional(
        render_frame, render_frame->blink_interface_registry_.get(),
        std::move(browser_interface_broker), frame_token, previous_web_frame,
        replicated_state->frame_policy,
        WebString::FromUTF8(replicated_state->name), web_view);
    // The new |web_frame| is a main frame iff the previous frame was.
    DCHECK_EQ(!previous_web_frame->Parent(), !web_frame->Parent());
    // Clone the current unique name so web tests that log frame unique names
    // output something meaningful. At `SwapIn()` time, the unique name will be
    // updated to the latest value.
    render_frame->unique_name_helper_.set_propagated_name(
        GetUniqueNameOfWebFrame(previous_web_frame));
  }

  CHECK(web_view);
  CHECK(render_frame);
  CHECK(web_frame);

  bool is_main_frame = !web_frame->Parent();

  // Child frames require there to be a |parent_routing_id| present, for the
  // remote parent frame. Though it is only used if the |previous_frame_token|
  // is not given, which happens in some corner cases.
  if (!is_main_frame)
    DCHECK(parent_frame_token);

  // We now have a WebLocalFrame for the new frame. The next step is to make
  // a RenderWidget (aka WebWidgetClient) for it, if it is a local root.
  // TODO(crbug.com/40387047): Can we merge this `is_main_frame` block with
  // RenderFrameImpl::CreateMainFrame()?
  if (is_main_frame) {
    // Main frames are always local roots, so they should always have a
    // |widget_params| (and it always comes with a routing id).
    DCHECK(widget_params);
    DCHECK_NE(widget_params->routing_id, IPC::mojom::kRoutingIdNone);

    render_frame->MaybeInitializeWidget(std::move(widget_params));

    // Note that we do *not* call WebView's DidAttachLocalMainFrame() here yet
    // because this frame is provisional and not attached to the Page yet. We
    // will tell WebViewImpl about it once it is swapped in.
  } else if (widget_params) {
    DCHECK(widget_params->routing_id != IPC::mojom::kRoutingIdNone);

    // This frame is a child local root, so we require a separate RenderWidget
    // for it from any other frames in the frame tree. Each local root defines
    // a separate context/coordinate space/world for compositing, painting,
    // input, etc. And each local root has a RenderWidget which provides
    // such services independent from other RenderWidgets.
    //
    // Notably, we do not attempt to reuse the main frame's RenderWidget (if the
    // main frame in this frame tree is local) as that RenderWidget is
    // functioning in a different local root. Because this is a child local
    // root, it implies there is some remote frame ancestor between this frame
    // and the main frame, thus its coordinate space etc is not known relative
    // to the main frame.
    render_frame->MaybeInitializeWidget(std::move(widget_params));
  }

  if (!is_on_initial_empty_document) {
    render_frame->frame_->SetIsNotOnInitialEmptyDocument();
  }

  render_frame->Initialize(web_frame->Parent());

  RendererNavigationMetricsManager::Instance().AddCreateFrameEvent(
      navigation_metrics_token, timer.start_time(), timer.Elapsed());
  // Add any new code above the AddCreateFrameEvent call.
}

// static
RenderFrame* RenderFrame::FromWebFrame(blink::WebLocalFrame* web_frame) {
  return RenderFrameImpl::FromWebFrame(web_frame);
}

// static
void RenderFrame::ForEach(RenderFrameVisitor* visitor) {
  DCHECK(RenderThread::IsMainThread());
  FrameMap* frames = g_frame_map.Pointer();
  for (auto it = frames->begin(); it != frames->end(); ++it) {
    if (!visitor->Visit(it->second))
      return;
  }
}

// static
RenderFrameImpl* RenderFrameImpl::FromWebFrame(blink::WebFrame* web_frame) {
  DCHECK(RenderThread::IsMainThread());
  auto iter = g_frame_map.Get().find(web_frame);
  if (iter != g_frame_map.Get().end())
    return iter->second;
  return nullptr;
}

// static
void RenderFrameImpl::InstallCreateHook(
    CreateRenderFrameImplFunction create_frame) {
  DCHECK(!g_create_render_frame_impl);
  g_create_render_frame_impl = create_frame;
}

blink::WebURL RenderFrameImpl::OverrideFlashEmbedWithHTML(
    const blink::WebURL& url) {
  return GetContentClient()->renderer()->OverrideFlashEmbedWithHTML(url);
}

// RenderFrameImpl::CreateParams --------------------------------------------

RenderFrameImpl::CreateParams::CreateParams(
    AgentSchedulingGroup& agent_scheduling_group,
    const blink::LocalFrameToken& frame_token,
    int32_t routing_id,
    mojo::PendingAssociatedReceiver<mojom::Frame> frame_receiver,
    mojo::PendingAssociatedRemote<blink::mojom::AssociatedInterfaceProvider>
        associated_interface_provider,
    const base::UnguessableToken& devtools_frame_token,
    bool is_for_nested_main_frame)
    : agent_scheduling_group(&agent_scheduling_group),
      frame_token(frame_token),
      routing_id(routing_id),
      frame_receiver(std::move(frame_receiver)),
      associated_interface_provider(std::move(associated_interface_provider)),
      devtools_frame_token(devtools_frame_token),
      is_for_nested_main_frame(is_for_nested_main_frame) {}
RenderFrameImpl::CreateParams::~CreateParams() = default;
RenderFrameImpl::CreateParams::CreateParams(CreateParams&&) = default;
RenderFrameImpl::CreateParams& RenderFrameImpl::CreateParams::operator=(
    CreateParams&&) = default;

// RenderFrameImpl ----------------------------------------------------------
RenderFrameImpl::RenderFrameImpl(CreateParams params)
    : agent_scheduling_group_(*params.agent_scheduling_group),
      is_main_frame_(true),
      unique_name_frame_adapter_(this),
      unique_name_helper_(&unique_name_frame_adapter_),
      in_frame_tree_(false),
      frame_token_(params.frame_token),
      process_label_id_(
          tracing::TrackNameRecorder::GetInstance()->GetNewProcessLabelId()),
      selection_text_offset_(0),
      selection_range_(gfx::Range::InvalidRange()),
      render_accessibility_manager_(
          std::make_unique<RenderAccessibilityManager>(this)),
      weak_wrapper_resource_load_info_notifier_(
          std::make_unique<blink::WeakWrapperResourceLoadInfoNotifier>(this)),
      navigation_client_impl_(nullptr),
      media_factory_(
          this,
          base::BindRepeating(&RenderFrameImpl::RequestOverlayRoutingToken,
                              base::Unretained(this))),
      devtools_frame_token_(params.devtools_frame_token),
      is_for_nested_main_frame_(params.is_for_nested_main_frame) {
  TRACE_EVENT_WITH_FLOW0("navigation", "RenderFrameImpl::RenderFrameImpl",
                         TRACE_ID_LOCAL(this), TRACE_EVENT_FLAG_FLOW_OUT);
  DCHECK(RenderThread::IsMainThread());
  blink_interface_registry_ = std::make_unique<BlinkInterfaceRegistryImpl>(
      registry_.GetWeakPtr(), associated_interfaces_.GetWeakPtr());

  DCHECK(params.frame_receiver.is_valid());
  pending_frame_receiver_ = std::move(params.frame_receiver);

  // Save the pending remote for lazy binding in
  // `GetRemoteAssociatedInterfaces().
  DCHECK(params.associated_interface_provider.is_valid());
  pending_associated_interface_provider_remote_ =
      std::move(params.associated_interface_provider);

  delayed_state_sync_timer_.SetTaskRunner(
      agent_scheduling_group_->agent_group_scheduler().DefaultTaskRunner());

  // Must call after binding our own remote interfaces.
  media_factory_.SetupMojo();
}

mojom::FrameHost* RenderFrameImpl::GetFrameHost() {
  if (!frame_host_remote_.is_bound())
    GetRemoteAssociatedInterfaces()->GetInterface(&frame_host_remote_);
  return frame_host_remote_.get();
}

RenderFrameImpl::~RenderFrameImpl() {
  TRACE_EVENT_WITH_FLOW0("navigation", "RenderFrameImpl::~RenderFrameImpl",
                         TRACE_ID_LOCAL(this), TRACE_EVENT_FLAG_FLOW_IN);
  for (auto& observer : observers_)
    observer.OnDestruct();
  for (auto& observer : observers_)
    observer.RenderFrameGone();

  web_media_stream_device_observer_.reset();

  if (initialized_ && is_main_frame_)
    MainFrameCounter::DecrementCount();

  tracing::TrackNameRecorder::GetInstance()->RemoveProcessLabel(
      process_label_id_);
  agent_scheduling_group_->RemoveFrameRoute(frame_token_);
}

void RenderFrameImpl::Initialize(blink::WebFrame* parent) {
  initialized_ = true;
  is_main_frame_ = !parent;
  if (is_main_frame_)
    MainFrameCounter::IncrementCount();

  TRACE_EVENT1("navigation,rail", "RenderFrameImpl::Initialize", "frame_token",
               frame_token_);

  RegisterMojoInterfaces();

  {
    TRACE_EVENT("navigation", "ContentRendererClient::RenderFrameCreated");
    // We delay calling this until we have the WebFrame so that any observer or
    // embedder can call GetWebFrame on any RenderFrame.
    GetContentClient()->renderer()->RenderFrameCreated(this);
  }

  // blink::AudioOutputIPCFactory::io_task_runner_ may be null in tests.
  auto& factory = blink::AudioOutputIPCFactory::GetInstance();
  if (factory.io_task_runner()) {
    factory.RegisterRemoteFactory(GetWebFrame()->GetLocalFrameToken(),
                                  GetBrowserInterfaceBroker());
  }

  // Bind this class to mojom::Frame and to the message router for legacy IPC.
  // These must be called after |frame_| is set since binding requires a
  // per-frame task runner.
  frame_receiver_.Bind(
      std::move(pending_frame_receiver_),
      GetTaskRunner(blink::TaskType::kInternalNavigationAssociated));
  agent_scheduling_group_->AddFrameRoute(
      frame_token_,
      this, GetTaskRunner(blink::TaskType::kInternalNavigationAssociated));
}

void RenderFrameImpl::GetInterface(
    const std::string& interface_name,
    mojo::ScopedMessagePipeHandle interface_pipe) {
  if (registry_.TryBindInterface(interface_name, &interface_pipe))
    return;

  for (auto& observer : observers_) {
    observer.OnInterfaceRequestForFrame(interface_name, &interface_pipe);
    if (!interface_pipe.is_valid())
      return;
  }
}

blink::WebFrameWidget* RenderFrameImpl::GetLocalRootWebFrameWidget() {
  return frame_->LocalRoot()->FrameWidget();
}

void RenderFrameImpl::ScriptedPrint() {
  bool user_initiated = GetLocalRootWebFrameWidget()->HandlingInputEvent();
  for (auto& observer : observers_)
    observer.ScriptedPrint(user_initiated);
}

void RenderFrameImpl::OnAssociatedInterfaceRequest(
    const std::string& interface_name,
    mojo::ScopedInterfaceEndpointHandle handle) {
  if (!associated_interfaces_.TryBindInterface(interface_name, &handle)) {
    for (auto& observer : observers_) {
      if (observer.OnAssociatedInterfaceRequestForFrame(interface_name,
                                                        &handle)) {
        return;
      }
    }
  }
}

void RenderFrameImpl::SetUpSharedMemoryForDroppedFrames(
    base::ReadOnlySharedMemoryRegion dropped_frames_memory) {
  TRACE_EVENT_WITH_FLOW0("navigation",
                         "RenderFrameImpl::SetUpSharedMemoryForDroppedFrames",
                         TRACE_ID_LOCAL(this),
                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  DCHECK(dropped_frames_memory.IsValid());
  for (auto& observer : observers_) {
    DCHECK(dropped_frames_memory.IsValid());
    if (observer.SetUpDroppedFramesReporting(dropped_frames_memory)) {
      break;
    }
  }
}

void RenderFrameImpl::BindAutoplayConfiguration(
    mojo::PendingAssociatedReceiver<blink::mojom::AutoplayConfigurationClient>
        receiver) {
  autoplay_configuration_receiver_.reset();
  autoplay_configuration_receiver_.Bind(
      std::move(receiver),
      GetTaskRunner(blink::TaskType::kInternalNavigationAssociated));
}

void RenderFrameImpl::BindFrameBindingsControl(
    mojo::PendingAssociatedReceiver<mojom::FrameBindingsControl> receiver) {
  frame_bindings_control_receiver_.Bind(
      std::move(receiver),
      GetTaskRunner(blink::TaskType::kInternalNavigationAssociated));
}

void RenderFrameImpl::BindNavigationClient(
    mojo::PendingAssociatedReceiver<mojom::NavigationClient> receiver) {
  // If the provisional owner frame is a local frame and it has a non-null
  // `navigation_client_impl_`, it began the navigation. Some properties need
  // to be copied over from the original `NavigationClient` to preserve
  // behaviour.
  NavigationClient* initiator_navigation_client = nullptr;
  WebFrame* initiator_frame = GetWebFrame()->GetProvisionalOwnerFrame();
  if (initiator_frame && initiator_frame->IsWebLocalFrame()) {
    initiator_navigation_client = RenderFrameImpl::FromWebFrame(initiator_frame)
                                      ->navigation_client_impl_.get();
  }
  navigation_client_impl_ =
      std::make_unique<NavigationClient>(this, initiator_navigation_client);
  navigation_client_impl_->Bind(std::move(receiver));
}

void RenderFrameImpl::BindNavigationClientWithParams(
    mojo::PendingAssociatedReceiver<mojom::NavigationClient> receiver,
    blink::mojom::BeginNavigationParamsPtr begin_params,
    blink::mojom::CommonNavigationParamsPtr common_params,
    bool is_duplicate_navigation) {
  if (navigation_client_impl_) {
    navigation_client_impl_->ResetForNewNavigation(is_duplicate_navigation);
  }
  navigation_client_impl_ = std::make_unique<NavigationClient>(
      this, std::move(begin_params), std::move(common_params));
  navigation_client_impl_->Bind(std::move(receiver));
}

// Unload this RenderFrame so the frame can navigate to a document rendered by
// a different process. We also allow this process to exit if there are no other
// active RenderFrames in it.
// This executes the unload handlers on this frame and its local descendants.
void RenderFrameImpl::Unload(
    bool is_loading,
    blink::mojom::FrameReplicationStatePtr replicated_frame_state,
    const blink::RemoteFrameToken& proxy_frame_token,
    blink::mojom::RemoteFrameInterfacesFromBrowserPtr remote_frame_interfaces,
    blink::mojom::RemoteMainFrameInterfacesPtr remote_main_frame_interfaces,
    const std::optional<base::UnguessableToken>& devtools_frame_token) {
  TRACE_EVENT1("navigation,rail", "RenderFrameImpl::UnloadFrame", "frame_token",
               frame_token_);
  DCHECK(!base::RunLoop::IsNestedOnCurrentThread());

  // Send an UpdateState message before we get deleted.
  // TODO(dcheng): Improve this comment to clarify why it's important to sent
  // state updates.
  SendUpdateState();

  // Before `this` is destroyed, save any fields needed to schedule a call to
  // `AgentSchedulingGroupHost::DidUnloadRenderFrame()`. The acknowledgement
  // itself is asynchronous to ensure that any postMessage calls (which schedule
  // IPCs as well) made from unload handlers are routed to the browser process
  // before the corresponding `RenderFrameHostImpl` is torn down.
  auto& agent_scheduling_group = *agent_scheduling_group_;
  blink::LocalFrameToken frame_token = frame_->GetLocalFrameToken();
  scoped_refptr<base::SingleThreadTaskRunner> task_runner =
      GetTaskRunner(blink::TaskType::kInternalPostMessageForwarding);

  // Important: |this| is deleted after this call!
  if (!SwapOutAndDeleteThis(
          is_loading, std::move(replicated_frame_state), proxy_frame_token,
          std::move(remote_frame_interfaces),
          std::move(remote_main_frame_interfaces), devtools_frame_token)) {
    // The swap is cancelled because running the unload handlers ended up
    // detaching this frame.
    return;
  }

  // Notify the browser that this frame was swapped out. Use the cached
  // `AgentSchedulingGroup` because |this| is deleted. Post a task to send the
  // ACK, so that any postMessage IPCs scheduled from the unload handler are
  // sent before the ACK (see https://crbug.com/857274).
  auto send_unload_ack = base::BindOnce(
      [](AgentSchedulingGroup* agent_scheduling_group,
         const blink::LocalFrameToken& frame_token) {
        agent_scheduling_group->DidUnloadRenderFrame(frame_token);
      },
      &agent_scheduling_group, frame_token);
  task_runner->PostTask(FROM_HERE, std::move(send_unload_ack));
}

void RenderFrameImpl::Delete(mojom::FrameDeleteIntention intent) {
  TRACE_EVENT(
      "navigation", "RenderFrameImpl::Delete", [&](perfetto::EventContext ctx) {
        auto* event = ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>();
        auto* data = event->set_render_frame_impl_deletion();
        data->set_intent(FrameDeleteIntentionToProto(intent));
      });
  base::ScopedUmaHistogramTimer histogram_timer("Navigation.RenderFrameDelete");
  // The main frame (when not provisional) is owned by the renderer's frame tree
  // via WebViewImpl. When a provisional main frame is swapped in, the ownership
  // moves from the browser to the renderer, but this happens in the renderer
  // process and is then the browser is informed.
  // If the provisional main frame is swapped in while the browser is destroying
  // it, the browser may request to delete |this|, thinking it has ownership
  // of it, but the renderer has already taken ownership via SwapIn().
  switch (intent) {
    case mojom::FrameDeleteIntention::kNotMainFrame:
      // The frame was not a main frame, so the browser should always have
      // ownership of it and we can just proceed with deleting it on
      // request.
      DCHECK(!is_main_frame_);
      break;
    case mojom::FrameDeleteIntention::kSpeculativeMainFrameForShutdown:
      // In this case the renderer has taken ownership of the provisional main
      // frame but the browser did not know yet and is shutting down. We can
      // ignore this request as the frame will be destroyed when the RenderView
      // is. This handles the shutdown case of https://crbug.com/957858.
      DCHECK(is_main_frame_);
      if (in_frame_tree_)
        return;
      break;
    case mojom::FrameDeleteIntention::
        kSpeculativeMainFrameForNavigationCancelled:
      // In this case the browser was navigating and cancelled the speculative
      // navigation. The renderer *should* undo the SwapIn() but the old state
      // has already been destroyed. Both ignoring the message or handling it
      // would leave the renderer in an inconsistent state now. If we ignore it
      // then the browser thinks the `blink::WebView` has a remote main frame,
      // but it is incorrect. If we handle it, then we are deleting a local main
      // frame out from under the `blink::WebView` and we will have bad pointers
      // in the renderer. So all we can do is crash. We should instead prevent
      // this scenario by blocking the browser from dropping the speculative
      // main frame when a commit (and ownership transfer) is imminent.
      // TODO(dcheng): This is the case of https://crbug.com/838348.
      DCHECK(is_main_frame_);
#if !BUILDFLAG(IS_ANDROID)
      CHECK(!in_frame_tree_);
#else
      // Previously this CHECK() was disabled on Android because it was much
      // easier to hit the race there.
      CHECK(!in_frame_tree_);
#endif  // !BUILDFLAG(IS_ANDROID)
      break;
  }

  // This will result in a call to RenderFrameImpl::FrameDetached, which
  // deletes the object. Do not access |this| after detach.
  frame_->Detach();
}

void RenderFrameImpl::UndoCommitNavigation(
    bool is_loading,
    blink::mojom::FrameReplicationStatePtr replicated_frame_state,
    const blink::RemoteFrameToken& proxy_frame_token,
    blink::mojom::RemoteFrameInterfacesFromBrowserPtr remote_frame_interfaces,
    blink::mojom::RemoteMainFrameInterfacesPtr remote_main_frame_interfaces) {
  // The browser process asked `this` to commit a navigation but has now decided
  // to discard the speculative RenderFrameHostImpl instead, since the
  // associated navigation was cancelled or replaced. However, the browser
  // process hasn't heard the `DidCommitNavigation()` yet, so pretend that the
  // commit never happened by immediately swapping `this` back to a proxy.
  //
  // This means that any state changes triggered by the already-swapped in
  // RenderFrame will simply be ignored, but that can't be helped: the
  // browser-side RFH will be gone before any outgoing IPCs from the renderer
  // for this RenderFrame (which by definition, are still in-flight) will be
  // processed by the browser process (as it has not yet seen the
  // `DidCommitNavigation()`).
  SwapOutAndDeleteThis(is_loading, std::move(replicated_frame_state),
                       proxy_frame_token, std::move(remote_frame_interfaces),
                       std::move(remote_main_frame_interfaces),
                       /*devtools_frame_token=*/std::nullopt);
}

void RenderFrameImpl::SnapshotAccessibilityTree(
    mojom::SnapshotAccessibilityTreeParamsPtr params,
    SnapshotAccessibilityTreeCallback callback) {
  ui::AXTreeUpdate response;
  AXTreeSnapshotterImpl snapshotter(this, ui::AXMode(params->ax_mode));
  snapshotter.Snapshot(params->max_nodes, params->timeout, &response);
  std::move(callback).Run(response);
}

void RenderFrameImpl::GetSerializedHtmlWithLocalLinks(
    const base::flat_map<GURL, base::FilePath>& url_map,
    const base::flat_map<blink::FrameToken, base::FilePath>& frame_token_map,
    bool save_with_empty_url,
    mojo::PendingRemote<mojom::FrameHTMLSerializerHandler> handler_remote) {
  // Convert input to the canonical way of passing a map into a Blink API.
  LinkRewritingDelegate delegate(url_map, frame_token_map);
  RenderFrameWebFrameSerializerClient client(std::move(handler_remote));

  // Serialize the frame (without recursing into subframes).
  WebFrameSerializer::Serialize(GetWebFrame(), &client, &delegate,
                                save_with_empty_url);
}

void RenderFrameImpl::SetWantErrorMessageStackTrace() {
  want_error_message_stack_trace_ = true;
  GetAgentGroupScheduler().Isolate()->SetCaptureStackTraceForUncaughtExceptions(
      true);
}

void RenderFrameImpl::NotifyObserversOfFailedProvisionalLoad() {
  for (auto& observer : observers_)
    observer.DidFailProvisionalLoad();
}

void RenderFrameImpl::DidMeaningfulLayout(
    blink::WebMeaningfulLayout layout_type) {
  for (auto& observer : observers_)
    observer.DidMeaningfulLayout(layout_type);
}

RenderFrame* RenderFrameImpl::GetMainRenderFrame() {
  WebFrame* main_frame = GetWebView()->MainFrame();
  DCHECK(main_frame);
  if (!main_frame->IsWebLocalFrame())
    return nullptr;
  return RenderFrame::FromWebFrame(main_frame->ToWebLocalFrame());
}

RenderAccessibility* RenderFrameImpl::GetRenderAccessibility() {
  return render_accessibility_manager_->GetRenderAccessibilityImpl();
}

std::unique_ptr<AXTreeSnapshotter> RenderFrameImpl::CreateAXTreeSnapshotter(
    ui::AXMode ax_mode) {
  return std::make_unique<AXTreeSnapshotterImpl>(this, ax_mode);
}

blink::WebLocalFrame* RenderFrameImpl::GetWebFrame() {
  DCHECK(frame_);
  return frame_;
}

const blink::WebLocalFrame* RenderFrameImpl::GetWebFrame() const {
  DCHECK(frame_);
  return frame_;
}

blink::WebView* RenderFrameImpl::GetWebView() {
  blink::WebView* web_view = GetWebFrame()->View();
  DCHECK(web_view);
  return web_view;
}

const blink::WebView* RenderFrameImpl::GetWebView() const {
  const blink::WebView* web_view = GetWebFrame()->View();
  DCHECK(web_view);
  return web_view;
}

const blink::web_pref::WebPreferences& RenderFrameImpl::GetBlinkPreferences() {
  return GetWebView()->GetWebPreferences();
}

const blink::RendererPreferences& RenderFrameImpl::GetRendererPreferences()
    const {
  return GetWebView()->GetRendererPreferences();
}

void RenderFrameImpl::ShowVirtualKeyboard() {
  GetLocalRootWebFrameWidget()->ShowVirtualKeyboard();
}

void RenderFrameImpl::ExecuteJavaScript(const std::u16string& javascript) {
  v8::HandleScope handle_scope(GetAgentGroupScheduler().Isolate());
  frame_->ExecuteScript(WebScriptSource(WebString::FromUTF16(javascript)));
}

void RenderFrameImpl::BindLocalInterface(
    const std::string& interface_name,
    mojo::ScopedMessagePipeHandle interface_pipe) {
  GetInterface(interface_name, std::move(interface_pipe));
}

blink::AssociatedInterfaceRegistry*
RenderFrameImpl::GetAssociatedInterfaceRegistry() {
  return &associated_interfaces_;
}

blink::AssociatedInterfaceProvider*
RenderFrameImpl::GetRemoteAssociatedInterfaces() {
  if (!remote_associated_interfaces_) {
    DCHECK(pending_associated_interface_provider_remote_);
    remote_associated_interfaces_ =
        std::make_unique<blink::AssociatedInterfaceProvider>(
            std::move(pending_associated_interface_provider_remote_),
            GetTaskRunner(blink::TaskType::kInternalNavigationAssociated));
  }
  return remote_associated_interfaces_.get();
}

void RenderFrameImpl::SetSelectedText(const std::u16string& selection_text,
                                      size_t offset,
                                      const gfx::Range& range) {
  GetWebFrame()->TextSelectionChanged(WebString::FromUTF16(selection_text),
                                      static_cast<uint32_t>(offset), range);
}

void RenderFrameImpl::AddMessageToConsole(
    blink::mojom::ConsoleMessageLevel level,
    const std::string& message) {
  AddMessageToConsoleImpl(level, message, false /* discard_duplicates */);
}

bool RenderFrameImpl::IsPasting() {
  return GetLocalRootWebFrameWidget()->IsPasting();
}

// blink::mojom::AutoplayConfigurationClient implementation
// --------------------------

void RenderFrameImpl::AddAutoplayFlags(const url::Origin& origin,
                                       const int32_t flags) {
  // If the origin is the same as the previously stored flags then we should
  // merge the two sets of flags together.
  if (autoplay_flags_.first == origin) {
    autoplay_flags_.second |= flags;
  } else {
    autoplay_flags_ = std::make_pair(origin, flags);
  }
}

// blink::mojom::ResourceLoadInfoNotifier implementation
// --------------------------

#if BUILDFLAG(IS_ANDROID)
void RenderFrameImpl::NotifyUpdateUserGestureCarryoverInfo() {
  GetFrameHost()->UpdateUserGestureCarryoverInfo();
}
#endif

void RenderFrameImpl::NotifyResourceRedirectReceived(
    const net::RedirectInfo& redirect_info,
    network::mojom::URLResponseHeadPtr redirect_response) {}

void RenderFrameImpl::NotifyResourceResponseReceived(
    int64_t request_id,
    const url::SchemeHostPort& final_response_url,
    network::mojom::URLResponseHeadPtr response_head,
    network::mojom::RequestDestination request_destination,
    bool is_ad_resource) {
  if (!blink::IsRequestDestinationFrame(request_destination)) {
    bool notify = ShouldNotifySubresourceResponseStarted(
        GetWebView()->GetRendererPreferences());
    UMA_HISTOGRAM_BOOLEAN(
        "Renderer.ReduceSubresourceResponseIPC.DidNotifyBrowser", notify);
    if (notify) {
      GetFrameHost()->SubresourceResponseStarted(final_response_url,
                                                 response_head->cert_status);
    }
  }
  DidStartResponse(final_response_url, request_id, std::move(response_head),
                   request_destination, is_ad_resource);
}

void RenderFrameImpl::NotifyResourceTransferSizeUpdated(
    int64_t request_id,
    int32_t transfer_size_diff) {
  DidReceiveTransferSizeUpdate(request_id, transfer_size_diff);
}

void RenderFrameImpl::NotifyResourceLoadCompleted(
    blink::mojom::ResourceLoadInfoPtr resource_load_info,
    const network::URLLoaderCompletionStatus& status) {
  DidCompleteResponse(resource_load_info->request_id, status);
  GetFrameHost()->ResourceLoadComplete(std::move(resource_load_info));
}

void RenderFrameImpl::NotifyResourceLoadCanceled(int64_t request_id) {
  DidCancelResponse(request_id);
}

void RenderFrameImpl::Clone(
    mojo::PendingReceiver<blink::mojom::ResourceLoadInfoNotifier>
        pending_resource_load_info_notifier) {
  resource_load_info_notifier_receivers_.Add(
      this, std::move(pending_resource_load_info_notifier),
      agent_scheduling_group_->agent_group_scheduler().DefaultTaskRunner());
}

void RenderFrameImpl::GetInterfaceProvider(
    mojo::PendingReceiver<service_manager::mojom::InterfaceProvider> receiver) {
  auto task_runner = GetTaskRunner(blink::TaskType::kInternalDefault);
  DCHECK(task_runner);
  interface_provider_receivers_.Add(this, std::move(receiver), task_runner);
}

void RenderFrameImpl::AllowBindings(int64_t enabled_bindings_flags) {
  auto new_bindings =
      BindingsPolicySet::FromEnumBitmask(enabled_bindings_flags);
  enabled_bindings_.PutAll(new_bindings);

  if (new_bindings.Has(BindingsPolicyValue::kMojoWebUi)) {
    // If mojo web UI is being enabled, update the protected memory bool to
    // allow MojoJS binding in this process.
    blink::WebV8Features::AllowMojoJSForProcess();
  }
}

void RenderFrameImpl::EnableMojoJsBindings(
    content::mojom::ExtraMojoJsFeaturesPtr features) {
  enable_mojo_js_bindings_ = true;
  mojo_js_features_ = std::move(features);

  // Update the protected memory bool to allow MojoJS binding in this process.
  blink::WebV8Features::AllowMojoJSForProcess();
}

void RenderFrameImpl::EnableMojoJsBindingsWithBroker(
    mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker> broker) {
  mojo_js_interface_broker_ = std::move(broker);

  // Update the protected memory bool to allow MojoJS binding in this process.
  blink::WebV8Features::AllowMojoJSForProcess();
}

void RenderFrameImpl::BindWebUI(
    mojo::PendingAssociatedReceiver<mojom::WebUI> receiver,
    mojo::PendingAssociatedRemote<mojom::WebUIHost> remote) {
  DCHECK(enabled_bindings_.Has(BindingsPolicyValue::kWebUi));
  WebUIExtensionData::Create(this, std::move(receiver), std::move(remote));
}

void RenderFrameImpl::SetOldPageLifecycleStateFromNewPageCommitIfNeeded(
    const blink::mojom::OldPageInfo* old_page_info,
    const GURL& new_page_url) {
  if (!old_page_info)
    return;

  WebLocalFrame* old_main_web_frame = WebLocalFrame::FromFrameToken(
      old_page_info->frame_token_for_old_main_frame);
  if (!old_main_web_frame) {
    // Even if we sent a valid `frame_token_for_old_main_frame`, it might have
    // already been destroyed by the time we try to get the WebLocalFrame, so
    // we should check if it still exists.
    return;
  }
  RenderFrameImpl* old_main_render_frame =
      RenderFrameImpl::FromWebFrame(old_main_web_frame);
  if (!old_main_render_frame) {
    return;
  }
  if (!IsMainFrame() && !old_main_render_frame->IsMainFrame()) {
    // This shouldn't happen because `old_page_info` should only be set on
    // cross-BrowsingInstance navigations, which can only happen on main frames.
    // However, we got some reports of this happening (see
    // https://crbug.com/1207271).
    SCOPED_CRASH_KEY_BOOL("old_page_info", "new_is_main_frame", IsMainFrame());
    SCOPED_CRASH_KEY_STRING256("old_page_info", "new_url", new_page_url.spec());
    SCOPED_CRASH_KEY_BOOL("old_page_info", "old_is_main_frame",
                          old_main_render_frame->IsMainFrame());
    SCOPED_CRASH_KEY_STRING256("old_page_info", "old_url",
                               old_main_render_frame->GetLoadingUrl().spec());
    SCOPED_CRASH_KEY_BOOL(
        "old_page_info", "old_is_frozen",
        old_page_info->new_lifecycle_state_for_old_page->is_frozen);
    SCOPED_CRASH_KEY_BOOL("old_page_info", "old_is_in_bfcache",
                          old_page_info->new_lifecycle_state_for_old_page
                              ->is_in_back_forward_cache);
    SCOPED_CRASH_KEY_BOOL(
        "old_page_info", "old_is_hidden",
        old_page_info->new_lifecycle_state_for_old_page->visibility ==
            blink::mojom::PageVisibilityState::kHidden);
    SCOPED_CRASH_KEY_BOOL(
        "old_page_info", "old_pagehide_dispatch",
        old_page_info->new_lifecycle_state_for_old_page->pagehide_dispatch ==
            blink::mojom::PagehideDispatch::kNotDispatched);
    CaptureTraceForNavigationDebugScenario(
        DebugScenario::kDebugNonMainFrameWithOldPageInfo);
    return;
  }
  DCHECK_EQ(old_page_info->new_lifecycle_state_for_old_page->visibility,
            blink::mojom::PageVisibilityState::kHidden);
  DCHECK_NE(old_page_info->new_lifecycle_state_for_old_page->pagehide_dispatch,
            blink::mojom::PagehideDispatch::kNotDispatched);
  old_main_web_frame->View()->SetPageLifecycleStateFromNewPageCommit(
      old_page_info->new_lifecycle_state_for_old_page->visibility,
      old_page_info->new_lifecycle_state_for_old_page->pagehide_dispatch);
}

void RenderFrameImpl::CommitNavigation(
    blink::mojom::CommonNavigationParamsPtr common_params,
    blink::mojom::CommitNavigationParamsPtr commit_params,
    network::mojom::URLResponseHeadPtr response_head,
    mojo::ScopedDataPipeConsumerHandle response_body,
    network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
    std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
        subresource_loader_factories,
    std::optional<std::vector<blink::mojom::TransferrableURLLoaderPtr>>
        subresource_overrides,
    blink::mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info,
    blink::mojom::ServiceWorkerContainerInfoForClientPtr container_info,
    mojo::PendingRemote<network::mojom::URLLoaderFactory>
        subresource_proxying_loader_factory,
    mojo::PendingRemote<network::mojom::URLLoaderFactory>
        keep_alive_loader_factory,
    mojo::PendingAssociatedRemote<blink::mojom::FetchLaterLoaderFactory>
        fetch_later_loader_factory,
    const blink::DocumentToken& document_token,
    const base::UnguessableToken& devtools_navigation_token,
    const base::Uuid& base_auction_nonce,
    const std::optional<network::ParsedPermissionsPolicy>& permissions_policy,
    blink::mojom::PolicyContainerPtr policy_container,
    mojo::PendingRemote<blink::mojom::CodeCacheHost> code_cache_host,
    mojo::PendingRemote<blink::mojom::CodeCacheHost>
        code_cache_host_for_background,
    mojom::CookieManagerInfoPtr cookie_manager_info,
    mojom::StorageInfoPtr storage_info,
    mojom::NavigationClient::CommitNavigationCallback commit_callback) {
  RendererNavigationMetricsManager::Instance().MarkCommitStart(
      commit_params->navigation_metrics_token);
  if (!response_head->client_side_content_decoding_types.empty()) {
    // Attempt to create the data pipe needed for content decoding.
    auto data_pipe_pair =
        network::ContentDecodingInterceptor::CreateDataPipePair(
            network::ContentDecodingInterceptor::ClientType::kCommitNavigation);
    if (data_pipe_pair) {
      // If pipe creation succeeds, intercept the response to set up decoding.
      network::ContentDecodingInterceptor::Intercept(
          response_head->client_side_content_decoding_types,
          url_loader_client_endpoints, response_body,
          std::move(*data_pipe_pair),
          base::ThreadPool::CreateSequencedTaskRunner(
              {base::TaskPriority::USER_BLOCKING}));
    } else {
      // Handle data pipe creation failure. This is rare but can happen if
      // shared memory is exhausted. In such a situation, the page load will
      // likely fail anyway as resources cannot be properly loaded. However, we
      // should avoid crashing the renderer process or attempting to display the
      // raw encoded body. Instead, discard the response body and log a console
      // error message for debugging and testing purposes.
      response_body.reset();
      AddMessageToConsole(blink::mojom::ConsoleMessageLevel::kError,
                          "Failed to decode content");
    }
  }
  base::ElapsedTimer timer;
  base::ScopedUmaHistogramTimer histogram_timer(kCommitRenderFrame);
  base::ScopedUmaHistogramTimer histogram_timer_frame(base::StrCat(
      {kCommitRenderFrame, IsMainFrame() ? ".MainFrame" : ".Subframe"}));
  TRACE_EVENT_WITH_FLOW0("navigation", "RenderFrameImpl::CommitNavigation",
                         TRACE_ID_LOCAL(this),
                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  DCHECK(navigation_client_impl_);
  DCHECK(!blink::IsRendererDebugURL(common_params->url));
  DCHECK(!NavigationTypeUtils::IsSameDocument(common_params->navigation_type));
  LogCommitHistograms(commit_params->commit_sent, is_main_frame_,
                      common_params->url);

  // Clear the `redirects` array to ensure it is not accidentally used somewhere
  // downstream of this code.
  if (base::FeatureList::IsEnabled(
          blink::features::kRemoveCommitRedirectUrlsArray)) {
    commit_params->redirects.clear();
  }

  bool is_new_navigation_in_outermost_main_frame_with_http_or_https = false;
  if (frame_->IsOutermostMainFrame() &&
      common_params->url.SchemeIsHTTPOrHTTPS()) {
    switch (common_params->navigation_type) {
      case blink::mojom::NavigationType::DIFFERENT_DOCUMENT:
        is_new_navigation_in_outermost_main_frame_with_http_or_https = true;
        break;
      case blink::mojom::NavigationType::RELOAD:
      case blink::mojom::NavigationType::RELOAD_BYPASSING_CACHE:
      case blink::mojom::NavigationType::RESTORE:
      case blink::mojom::NavigationType::RESTORE_WITH_POST:
      case blink::mojom::NavigationType::HISTORY_SAME_DOCUMENT:
      case blink::mojom::NavigationType::HISTORY_DIFFERENT_DOCUMENT:
      case blink::mojom::NavigationType::SAME_DOCUMENT:
        break;
    }
  }

  AssertNavigationCommits assert_navigation_commits(
      this, kMayReplaceInitialEmptyDocument);

  SetOldPageLifecycleStateFromNewPageCommitIfNeeded(
      commit_params->old_page_info.get(), common_params->url);

  bool was_initiated_in_this_frame =
      navigation_client_impl_ &&
      navigation_client_impl_->was_initiated_in_this_frame();

  // Sanity check that the browser always sends us new loader factories on
  // cross-document navigations.
  DCHECK(common_params->url.SchemeIs(url::kJavaScriptScheme) ||
         subresource_loader_factories);

  int request_id = blink::GenerateRequestId();
  std::unique_ptr<DocumentState> document_state = BuildDocumentStateFromParams(
      *common_params, *commit_params, std::move(commit_callback),
      std::move(navigation_client_impl_), request_id,
      was_initiated_in_this_frame);

  // Check if the navigation being committed originated as a client redirect.
  bool is_client_redirect =
      !!(common_params->transition & ui::PAGE_TRANSITION_CLIENT_REDIRECT);
  auto navigation_params = std::make_unique<WebNavigationParams>(
      document_token, devtools_navigation_token, base_auction_nonce);
  navigation_params->navigation_delivery_type =
      commit_params->navigation_delivery_type;
  navigation_params->is_client_redirect = is_client_redirect;
  FillMiscNavigationParams(*common_params, *commit_params,
                           navigation_params.get());
  navigation_params->policy_container =
      ToWebPolicyContainer(std::move(policy_container));
  navigation_params->view_transition_state =
      std::move(commit_params->view_transition_state);

  if (frame_->IsOutermostMainFrame() && permissions_policy) {
    navigation_params->permissions_policy_override = permissions_policy;
  }

  auto commit_with_params = base::BindOnce(
      &RenderFrameImpl::CommitNavigationWithParams, weak_factory_.GetWeakPtr(),
      common_params.Clone(), commit_params.Clone(),
      std::move(subresource_loader_factories), std::move(subresource_overrides),
      std::move(controller_service_worker_info), std::move(container_info),
      std::move(subresource_proxying_loader_factory),
      std::move(keep_alive_loader_factory),
      std::move(fetch_later_loader_factory), std::move(code_cache_host),
      std::move(code_cache_host_for_background), std::move(cookie_manager_info),
      std::move(storage_info), std::move(document_state));

  // Handle a navigation that has a non-empty `data_url_as_string`, or perform
  // a "loadDataWithBaseURL" navigation, which is different from a normal data:
  // URL navigation in various ways:
  // - The "document URL" will use the supplied `base_url_for_data_url` if it's
  // not empty (otherwise it will fall back to the data: URL).
  // - The actual data: URL will be saved in the document's DocumentState to
  // later be returned as the `url` in DidCommitProvisionalLoadParams.
  bool should_handle_data_url_as_string = false;
#if BUILDFLAG(IS_ANDROID)
  should_handle_data_url_as_string |=
      is_main_frame_ && !commit_params->data_url_as_string.empty();
#endif

  if (should_handle_data_url_as_string ||
      commit_params->is_load_data_with_base_url) {
    std::string mime_type, charset, data;
    // `base_url` will be set to `base_url_for_data_url` from `common_params`,
    // unless it's empty (the `data_url_as_string` handling case), in which
    // case `url` from `common_params` will be used.
    GURL base_url;
    DecodeDataURL(*common_params, *commit_params, &mime_type, &charset, &data,
                  &base_url);
    // Note that even though we use the term "base URL", `base_url` is also
    // used as the "document URL" (unlike normal "base URL"s set through the
    // <base> element or other means, which would only be used to resolve
    // relative URLs, etc).
    navigation_params->url = base_url;
    WebNavigationParams::FillStaticResponse(navigation_params.get(),
                                            WebString::FromUTF8(mime_type),
                                            WebString::FromUTF8(charset), data);
    std::move(commit_with_params).Run(std::move(navigation_params));
    return;
  }

  FillNavigationParamsRequest(*common_params, *commit_params,
                              navigation_params.get());
  if (!url_loader_client_endpoints &&
      common_params->url.SchemeIs(url::kDataScheme)) {
    // Normally, data urls will have |url_loader_client_endpoints| set.
    // However, tests and interstitial pages pass data urls directly,
    // without creating url loader.
    std::string mime_type, charset, data;
    if (!net::DataURL::Parse(common_params->url, &mime_type, &charset, &data)) {
      NOTREACHED() << "Invalid URL passed: "
                   << common_params->url.possibly_invalid_spec();
    }
    WebNavigationParams::FillStaticResponse(navigation_params.get(),
                                            WebString::FromUTF8(mime_type),
                                            WebString::FromUTF8(charset), data);
  } else {
    blink::WebNavigationBodyLoader::FillNavigationParamsResponseAndBodyLoader(
        std::move(common_params), std::move(commit_params), request_id,
        response_head.Clone(), std::move(response_body),
        std::move(url_loader_client_endpoints),
        GetTaskRunner(blink::TaskType::kInternalLoading),
        CreateResourceLoadInfoNotifierWrapper(), !frame_->Parent(),
        navigation_params.get(), frame_->IsAdFrame());
  }

  // The MHTML mime type should be same as the one we check in the browser
  // process's download_utils::MustDownload.
  bool is_mhtml_archive = base::EqualsCaseInsensitiveASCII(
                              response_head->mime_type, "multipart/related") ||
                          base::EqualsCaseInsensitiveASCII(
                              response_head->mime_type, "message/rfc822");
  if (is_mhtml_archive && navigation_params->body_loader) {
    // Load full mhtml archive before committing navigation.
    // We need this to retrieve the document mime type prior to committing.
    mhtml_body_loader_client_ =
        std::make_unique<RenderFrameImpl::MHTMLBodyLoaderClient>(
            this, std::move(navigation_params), std::move(commit_with_params));
    // The navigation didn't really commit, but lie about it anyway. Why? MHTML
    // is a bit special: the renderer process is responsible for parsing the
    // archive, but at this point, the response body isn't fully loaded yet.
    // Instead, MHTMLBodyLoaderClient will read the entire response body and
    // parse the archive to extract the main resource to be committed.
    //
    // There are two possibilities from this point:
    // - |MHTMLBodyLoaderClient::BodyLoadingFinished()| is called. At that
    //   point, the main resource can be extracted, and the navigation will be
    //   synchronously committed. If |this| is a provisional frame, it will be
    //   swapped in and committed. A separate |AssertNavigationCommits| is
    //   instantiated in |MHTMLBodyLoaderClient::BodyLoadingFinished()| to
    //   assert the commit actually happens. ✔️
    // - Alternatively, the pending archive load may be cancelled. This can only
    //   happen if the renderer initiates a new navigation, or if the browser
    //   requests that this frame commit a different navigation.
    //   - If |this| is already swapped in, the reason for cancelling the
    //     pending archive load does not matter. There will be no state skew
    //     between the browser and the renderer, since |this| has already
    //     committed a navigation. ✔️
    //   - If |this| is provisional, the pending archive load may only be
    //     cancelled by the browser requesting |this| to commit a different
    //     navigation. AssertNavigationCommits ensures the new request ends up
    //     committing and swapping in |this|, so this is OK. ✔️
    navigation_commit_state_ = NavigationCommitState::kDidCommit;
    return;
  }

  // Common case - fill navigation params from provided information and commit.
  std::move(commit_with_params).Run(std::move(navigation_params));

  if (is_new_navigation_in_outermost_main_frame_with_http_or_https) {
    base::UmaHistogramTimes(
        base::StrCat({kCommitRenderFrame,
                      ".OutermostMainFrame.NewNavigation.IsHTTPOrHTTPS"}),
        timer.Elapsed());
  }
}

void RenderFrameImpl::CommitNavigationWithParams(
    blink::mojom::CommonNavigationParamsPtr common_params,
    blink::mojom::CommitNavigationParamsPtr commit_params,
    std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
        subresource_loader_factories,
    std::optional<std::vector<blink::mojom::TransferrableURLLoaderPtr>>
        subresource_overrides,
    blink::mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info,
    blink::mojom::ServiceWorkerContainerInfoForClientPtr container_info,
    mojo::PendingRemote<network::mojom::URLLoaderFactory>
        subresource_proxying_loader_factory,
    mojo::PendingRemote<network::mojom::URLLoaderFactory>
        keep_alive_loader_factory,
    mojo::PendingAssociatedRemote<blink::mojom::FetchLaterLoaderFactory>
        fetch_later_loader_factory,
    mojo::PendingRemote<blink::mojom::CodeCacheHost> code_cache_host,
    mojo::PendingRemote<blink::mojom::CodeCacheHost>
        code_cache_host_for_background,
    mojom::CookieManagerInfoPtr cookie_manager_info,
    mojom::StorageInfoPtr storage_info,
    std::unique_ptr<DocumentState> document_state,
    std::unique_ptr<WebNavigationParams> navigation_params) {
  TRACE_EVENT_WITH_FLOW0("navigation",
                         "RenderFrameImpl::CommitNavigationWithParams",
                         TRACE_ID_LOCAL(this),
                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  base::ElapsedTimer timer;
  if (common_params->url.IsAboutSrcdoc()) {
    WebNavigationParams::FillStaticResponse(navigation_params.get(),
                                            "text/html", "UTF-8",
                                            commit_params->srcdoc_value);
  }

  scoped_refptr<blink::ChildURLLoaderFactoryBundle> new_loader_factories =
      CreateLoaderFactoryBundle(std::move(subresource_loader_factories),
                                std::move(subresource_overrides),
                                std::move(subresource_proxying_loader_factory),
                                std::move(keep_alive_loader_factory),
                                std::move(fetch_later_loader_factory));

  DCHECK(new_loader_factories);
  DCHECK(new_loader_factories->HasBoundDefaultFactory());

  // If the navigation is for "view source", the WebLocalFrame needs to be put
  // in a special mode.
  if (commit_params->is_view_source)
    frame_->EnableViewSourceMode(true);

  if (frame_->IsOutermostMainFrame()) {
    // Save the Back/Forward Cache NotRestoredReasons struct to WebLocalFrame to
    // report for PerformanceNavigationTiming API.
    frame_->SetNotRestoredReasons(
        std::move(commit_params->not_restored_reasons));
  } else {
    // NotRestoredReasons are only set for the outermost main frame.
    CHECK(!commit_params->not_restored_reasons);
  }

  // |lcpp_hint| is set only when the frame is eligible (e.g. it's an outer
  // most main frame), which is checked in the browser process. Otherwise
  // nullptr.
  //
  // When there's a pre-existing LCPP hint on frame, we want to remove the
  // existing hint. Hence calling SetLCPPHint() is always required.
  CHECK(!commit_params->lcpp_hint || frame_->IsOutermostMainFrame());
  frame_->SetLCPPHint(std::move(commit_params->lcpp_hint));

  // Note: this intentionally does not call |Detach()| before |reset()|. If
  // there is an active |MHTMLBodyLoaderClient|, the browser-side navigation
  // code is explicitly replacing it with a new navigation commit request.
  // The check for |kWillCommit| in |~MHTMLBodyLoaderClient| covers this case.
  mhtml_body_loader_client_.reset();

  PrepareFrameForCommit(common_params->url, *commit_params);

  blink::WebFrameLoadType load_type =
      NavigationTypeToLoadType(common_params->navigation_type,
                               common_params->should_replace_current_entry);

  WebHistoryItem item_for_history_navigation;
  blink::mojom::CommitResult commit_status = blink::mojom::CommitResult::Ok;

  if (load_type == WebFrameLoadType::kBackForward ||
      load_type == WebFrameLoadType::kRestore) {
    // We must know the nav entry ID of the page we are navigating back to,
    // which should be the case because history navigations are routed via the
    // browser.
    DCHECK_NE(0, commit_params->nav_entry_id);

    // Check that the history navigation can commit.
    commit_status = PrepareForHistoryNavigationCommit(
        *common_params, *commit_params, &item_for_history_navigation,
        &load_type);
  }

  if (commit_status != blink::mojom::CommitResult::Ok) {
    // The browser expects the frame to be loading this navigation. Inform it
    // that the load stopped if needed.
    if (frame_ && !frame_->IsLoading())
      GetFrameHost()->DidStopLoading();
    return;
  }

  navigation_params->frame_load_type = load_type;
  navigation_params->history_item = item_for_history_navigation;

  navigation_params->load_with_storage_access =
      commit_params->load_with_storage_access;
  navigation_params->visited_link_salt = commit_params->visited_link_salt;

  if (!container_info) {
    // An empty network provider will always be created since it is expected in
    // a certain number of places.
    navigation_params->service_worker_network_provider =
        ServiceWorkerNetworkProviderForFrame::CreateInvalidInstance();
  } else {
    navigation_params->service_worker_network_provider =
        ServiceWorkerNetworkProviderForFrame::Create(
            this, std::move(container_info),
            std::move(controller_service_worker_info),
            network::SharedURLLoaderFactory::Create(
                new_loader_factories->Clone()));
  }

  DCHECK(!pending_loader_factories_);
  pending_loader_factories_ = std::move(new_loader_factories);
  pending_code_cache_host_ = std::move(code_cache_host);
  pending_code_cache_host_for_background_ =
      std::move(code_cache_host_for_background);
  pending_cookie_manager_info_ = std::move(cookie_manager_info);
  pending_storage_info_ = std::move(storage_info);
  original_storage_key_ = navigation_params->storage_key;

  base::WeakPtr<RenderFrameImpl> weak_self = weak_factory_.GetWeakPtr();
  frame_->CommitNavigation(std::move(navigation_params),
                           std::move(document_state));
  // The commit can result in this frame being removed.
  if (!weak_self)
    return;

  if (commit_params->local_surface_id) {
    CHECK(frame_->FrameWidget())
        << "Only local roots should get a SurfaceID update";
    frame_->FrameWidget()->ApplyLocalSurfaceIdUpdate(
        *commit_params->local_surface_id);
  }

  if (load_type == WebFrameLoadType::kStandard &&
      common_params->url.SchemeIsHTTPOrHTTPS()) {
    base::UmaHistogramMicrosecondsTimes(
        "Navigation.CommitNavigationWithParams.Time.IsStandardLoadType."
        "IsHTTPOrHTTPS",
        timer.Elapsed());
  }

  ResetMembersUsedForDurationOfCommit();
}

void RenderFrameImpl::CommitFailedNavigation(
    blink::mojom::CommonNavigationParamsPtr common_params,
    blink::mojom::CommitNavigationParamsPtr commit_params,
    bool has_stale_copy_in_cache,
    int error_code,
    int extended_error_code,
    net::ResolveErrorInfo resolve_error_info,
    const std::optional<std::string>& error_page_content,
    std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
        subresource_loader_factories,
    const blink::DocumentToken& document_token,
    const base::UnguessableToken& devtools_navigation_token,
    blink::mojom::PolicyContainerPtr policy_container,
    mojom::AlternativeErrorPageOverrideInfoPtr alternative_error_page_info,
    mojom::NavigationClient::CommitFailedNavigationCallback callback) {
  TRACE_EVENT1("navigation,benchmark,rail",
               "RenderFrameImpl::CommitFailedNavigation", "frame_token",
               frame_token_);
  RendererNavigationMetricsManager::Instance().MarkCommitStart(
      commit_params->navigation_metrics_token);
  DCHECK(navigation_client_impl_);
  DCHECK(!NavigationTypeUtils::IsSameDocument(common_params->navigation_type));

  // The browser process should not send us an initiator_base_url in a failed
  // navigation.
  DCHECK(!common_params->initiator_base_url);

  AssertNavigationCommits assert_navigation_commits(
      this, kMayReplaceInitialEmptyDocument);

  // Clear the `redirects` array to ensure it is not accidentally used somewhere
  // downstream of this code.
  if (base::FeatureList::IsEnabled(
          blink::features::kRemoveCommitRedirectUrlsArray)) {
    commit_params->redirects.clear();
  }

  GetWebView()->SetHistoryListFromNavigation(
      commit_params->current_history_list_index,
      commit_params->current_history_list_length);

  // Note: this intentionally does not call |Detach()| before |reset()|. If
  // there is an active |MHTMLBodyLoaderClient|, the browser-side navigation
  // code is explicitly replacing it with a new navigation commit request.
  // The check for |kWillCommit| in |~MHTMLBodyLoaderClient| covers this case.
  mhtml_body_loader_client_.reset();

  GetContentClient()->SetActiveURL(
      common_params->url, frame_->Top()->GetSecurityOrigin().ToString().Utf8());

  // TODO(lukasza): https://crbug.com/936696: No need to postpone setting the
  // |new_loader_factories| once we start swapping RenderFrame^H^H^H
  // RenderDocument on every cross-document navigation.
  scoped_refptr<blink::ChildURLLoaderFactoryBundle> new_loader_factories =
      CreateLoaderFactoryBundle(
          std::move(subresource_loader_factories),
          std::nullopt /* subresource_overrides */,
          mojo::NullRemote() /* subresource_proxying_loader_factory */,
          mojo::NullRemote() /* keep_alive_loader_factory */,
          mojo::NullAssociatedRemote() /* fetch_later_loader_factory */);
  DCHECK(new_loader_factories->HasBoundDefaultFactory());

  // Send the provisional load failure.
  WebURLError error(
      error_code, extended_error_code, resolve_error_info,
      has_stale_copy_in_cache ? WebURLError::HasCopyInCache::kTrue
                              : WebURLError::HasCopyInCache::kFalse,
      WebURLError::IsWebSecurityViolation::kFalse, common_params->url,
      WebURLError::ShouldCollapseInitiator::kFalse);

  // Since the URL will be set to kUnreachableWebDataURL, use default content
  // settings.
  commit_params->content_settings =
      blink::CreateDefaultRendererContentSettings();
  auto navigation_params = std::make_unique<WebNavigationParams>(
      document_token, devtools_navigation_token,
      /*base_auction_nonce=*/base::Uuid::GenerateRandomV4());
  FillNavigationParamsRequest(*common_params, *commit_params,
                              navigation_params.get());
  // Use kUnreachableWebDataURL as the document URL (instead of the URL that
  // failed to load, which is saved separately as the "unreachable URL" below).
  navigation_params->url = GURL(kUnreachableWebDataURL);
  // FillNavigationParamsRequest() sets the |navigation_params->http_method| to
  // the original method of the request. In successful page loads,
  // |navigation_params->redirects| also gets populated and the redirects are
  // later replayed to update the method. However, in the case of an error page
  // load, the redirects are neither populated nor replayed. Hence |http_method|
  // needs to be manually set to the final method.
  navigation_params->http_method = WebString::FromASCII(common_params->method);
  navigation_params->error_code = error_code;

  // This is already checked in `NavigationRequest::OnRequestFailedInternal` and
  // `NavigationRequest::OnFailureChecksCompleted` on the browser side, so the
  // renderer should never see this.
  CHECK_NE(net::ERR_ABORTED, error_code);

  if (commit_params->nav_entry_id == 0) {
    // For renderer initiated navigations, we send out a
    // DidFailProvisionalLoad() notification.
    NotifyObserversOfFailedProvisionalLoad();
  }

  std::string error_html;
  std::string* error_html_ptr = &error_html;
  if (error_code == net::ERR_HTTP_RESPONSE_CODE_FAILURE) {
    DCHECK_NE(commit_params->http_response_code, -1);
    GetContentClient()->renderer()->PrepareErrorPageForHttpStatusError(
        this, error, navigation_params->http_method.Ascii(),
        commit_params->http_response_code,
        std::move(alternative_error_page_info), error_html_ptr);
  } else {
    if (error_page_content) {
      error_html = error_page_content.value();
      error_html_ptr = nullptr;
    }
    // Prepare for the error page. Note that even if |error_html_ptr| is set to
    // null above, PrepareErrorPage might have other side effects e.g. setting
    // some error-related states, so we should still call it.
    GetContentClient()->renderer()->PrepareErrorPage(
        this, error, navigation_params->http_method.Ascii(),
        std::move(alternative_error_page_info), error_html_ptr);
  }

  // Make sure we never show errors in view source mode.
  frame_->EnableViewSourceMode(false);

  auto page_state =
      blink::PageState::CreateFromEncodedData(commit_params->page_state);
  if (page_state.IsValid())
    navigation_params->history_item = WebHistoryItem(page_state);
  if (!navigation_params->history_item.IsNull()) {
    if (common_params->navigation_type ==
            blink::mojom::NavigationType::RESTORE ||
        common_params->navigation_type ==
            blink::mojom::NavigationType::RESTORE_WITH_POST) {
      navigation_params->frame_load_type = WebFrameLoadType::kRestore;
    } else {
      navigation_params->frame_load_type = WebFrameLoadType::kBackForward;
    }
  } else if (common_params->should_replace_current_entry) {
    navigation_params->frame_load_type = WebFrameLoadType::kReplaceCurrentItem;
  }

  navigation_params->service_worker_network_provider =
      ServiceWorkerNetworkProviderForFrame::CreateInvalidInstance();
  FillMiscNavigationParams(*common_params, *commit_params,
                           navigation_params.get());
  WebNavigationParams::FillStaticResponse(navigation_params.get(), "text/html",
                                          "UTF-8", error_html);
  // Save the URL that failed to load as the "unreachable URL" so that the
  // we can use that (instead of kUnreachableWebDataURL) for the HistoryItem for
  // this navigation, and also to send back with the DidCommitProvisionalLoad
  // message to the browser.
  // TODO(crbug.com/40150370): Stop sending the URL back with DidCommit.
  navigation_params->unreachable_url = error.url();
  if (base::FeatureList::IsEnabled(
          blink::features::kRemoveCommitRedirectUrlsArray)) {
    if (commit_params->redirect_infos.size()) {
      navigation_params->pre_redirect_url_for_failed_navigations =
          common_params->url;
    } else {
      navigation_params->pre_redirect_url_for_failed_navigations = error.url();
    }
  } else {
   if (commit_params->redirects.size()) {
     navigation_params->pre_redirect_url_for_failed_navigations =
         commit_params->redirects[0];
   } else {
     navigation_params->pre_redirect_url_for_failed_navigations = error.url();
   }
  }

  navigation_params->policy_container =
      ToWebPolicyContainer(std::move(policy_container));

  navigation_params->view_transition_state =
      std::move(commit_params->view_transition_state);

  // The error page load (not to confuse with a failed load of original page)
  // was not initiated through BeginNavigation, therefore
  // |was_initiated_in_this_frame| is false.
  std::unique_ptr<DocumentState> document_state = BuildDocumentStateFromParams(
      *common_params, *commit_params, std::move(callback),
      std::move(navigation_client_impl_), blink::GenerateRequestId(),
      false /* was_initiated_in_this_frame */);

  DCHECK(!pending_loader_factories_);
  pending_loader_factories_ = std::move(new_loader_factories);

  // The load of the error page can result in this frame being removed.
  // Use a WeakPtr as an easy way to detect whether this has occurred. If so,
  // this method should return immediately and not touch any part of the object,
  // otherwise it will result in a use-after-free bug.
  base::WeakPtr<RenderFrameImpl> weak_this = weak_factory_.GetWeakPtr();
  frame_->CommitNavigation(std::move(navigation_params),
                           std::move(document_state));
  if (!weak_this)
    return;

  ResetMembersUsedForDurationOfCommit();
}

void RenderFrameImpl::CommitSameDocumentNavigation(
    blink::mojom::CommonNavigationParamsPtr common_params,
    blink::mojom::CommitNavigationParamsPtr commit_params,
    CommitSameDocumentNavigationCallback callback) {
  RendererNavigationMetricsManager::Instance().MarkCommitStart(
      commit_params->navigation_metrics_token);

  DCHECK(!blink::IsRendererDebugURL(common_params->url));
  DCHECK(!NavigationTypeUtils::IsReload(common_params->navigation_type));
  DCHECK(!commit_params->is_view_source);
  DCHECK(NavigationTypeUtils::IsSameDocument(common_params->navigation_type));

  CHECK(in_frame_tree_);

  // Unlike a cross-document navigation commit, detach the MHTMLBodyLoaderClient
  // before resetting it. In the case of a cross-document navigation, it's
  // important to ensure *something* commits, even if the original commit
  // request was replaced by a commit request. However, in the case of a
  // same-document navigation commit request, |this| must already be committed.
  //
  // Note that this means a same-document navigation might cancel a
  // cross-document navigation, which is a bit strange. In the future, explore
  // the idea of allowing the cross-document navigation to continue.
  if (mhtml_body_loader_client_) {
    mhtml_body_loader_client_->Detach();
    mhtml_body_loader_client_.reset();
  }

  PrepareFrameForCommit(common_params->url, *commit_params);

  blink::WebFrameLoadType load_type =
      NavigationTypeToLoadType(common_params->navigation_type,
                               common_params->should_replace_current_entry);

  DocumentState* document_state =
      DocumentState::FromDocumentLoader(frame_->GetDocumentLoader());
  document_state->set_navigation_state(
      NavigationState::CreateForSameDocumentCommitFromBrowser(
          std::move(common_params), std::move(commit_params),
          std::move(callback)));
  NavigationState* navigation_state = document_state->navigation_state();

  blink::mojom::CommitResult commit_status = blink::mojom::CommitResult::Ok;
  WebHistoryItem item_for_history_navigation;

  if (navigation_state->common_params().navigation_type ==
      blink::mojom::NavigationType::HISTORY_SAME_DOCUMENT) {
    DCHECK(blink::PageState::CreateFromEncodedData(
               navigation_state->commit_params().page_state)
               .IsValid());
    // We must know the nav entry ID of the page we are navigating back to,
    // which should be the case because history navigations are routed via the
    // browser.
    DCHECK_NE(0, navigation_state->commit_params().nav_entry_id);
    DCHECK(!navigation_state->common_params()
                .is_history_navigation_in_new_child_frame);
    commit_status = PrepareForHistoryNavigationCommit(
        navigation_state->common_params(), navigation_state->commit_params(),
        &item_for_history_navigation, &load_type);
  }

  if (commit_status == blink::mojom::CommitResult::Ok) {
    base::WeakPtr<RenderFrameImpl> weak_this = weak_factory_.GetWeakPtr();
    // Same-document navigations on data URLs loaded with a valid base URL
    // should keep the base URL as document URL.
    bool use_base_url_for_data_url =
        !navigation_state->common_params().base_url_for_data_url.is_empty();
#if BUILDFLAG(IS_ANDROID)
    use_base_url_for_data_url |=
        !navigation_state->commit_params().data_url_as_string.empty();
#endif

    GURL url;
    if (is_main_frame_ && use_base_url_for_data_url) {
      url = navigation_state->common_params().base_url_for_data_url;
    } else {
      url = navigation_state->common_params().url;
    }
    bool is_client_redirect = !!(navigation_state->common_params().transition &
                                 ui::PAGE_TRANSITION_CLIENT_REDIRECT);
    bool started_with_transient_activation =
        navigation_state->common_params().has_user_gesture;
    bool is_browser_initiated =
        navigation_state->commit_params().is_browser_initiated;
    bool has_ua_visual_transition =
        navigation_state->commit_params().has_ua_visual_transition;
    std::optional<blink::scheduler::TaskAttributionId>
        soft_navigation_heuristics_task_id =
            navigation_state->commit_params()
                .soft_navigation_heuristics_task_id;

    WebSecurityOrigin initiator_origin;
    if (navigation_state->common_params().initiator_origin) {
      initiator_origin =
          navigation_state->common_params().initiator_origin.value();
    }
    bool should_skip_screenshot =
        navigation_state->commit_params().should_skip_screenshot;

    // Load the request.
    commit_status = frame_->CommitSameDocumentNavigation(
        url, load_type, item_for_history_navigation, is_client_redirect,
        started_with_transient_activation, initiator_origin,
        is_browser_initiated, has_ua_visual_transition,
        soft_navigation_heuristics_task_id, should_skip_screenshot);

    // If `commit_status` is Ok, RunCommitSameDocumentNavigationCallback() was
    // called in DidCommitNavigationInternal() or the NavigationApi deferred the
    // commit and will call DidCommitNavigationInternal() when the commit is
    // undeferred. Either way, no further work is needed here.
    if (commit_status == blink::mojom::CommitResult::Ok) {
      return;
    }

    // The load of the URL can result in this frame being removed. Use a
    // WeakPtr as an easy way to detect whether this has occurred. If so, this
    // method should return immediately and not touch any part of the object,
    // otherwise it will result in a use-after-free bug.
    // Similarly, check whether `navigation_state` is still the state associated
    // with the WebDocumentLoader. It may have been preempted by a navigation
    // started by an event handler.
    if (!weak_this || document_state->navigation_state() != navigation_state) {
      return;
    }
  }

  DCHECK_NE(commit_status, blink::mojom::CommitResult::Ok);
  navigation_state->RunCommitSameDocumentNavigationCallback(commit_status);
  document_state->clear_navigation_state();

  // The browser expects the frame to be loading this navigation. Inform it
  // that the load stopped if needed.
  if (frame_ && !frame_->IsLoading()) {
    GetFrameHost()->DidStopLoading();
  }
}

void RenderFrameImpl::UpdateSubresourceLoaderFactories(
    std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
        subresource_loader_factories) {
  if (loader_factories_->IsHostChildURLLoaderFactoryBundle()) {
    static_cast<blink::HostChildURLLoaderFactoryBundle*>(
        loader_factories_.get())
        ->UpdateThisAndAllClones(std::move(subresource_loader_factories));
  } else {
    // RFHI::recreate_default_url_loader_factory_after_network_service_crash_ is
    // only set for frames that directly get their factory bundle from the
    // browser (HostChildURLLoaderFactoryBundle) rather than inheriting the
    // bundle from another frame (TrackedChildURLLoaderFactoryBundle).
    // Therefore the default factory *may* be present in the `if`/true branch
    // and *must* be missing in the `else` branch.
    DCHECK(!subresource_loader_factories->pending_default_factory().is_valid());

    // If there is no `pending_default_factory` (see the DCHECK above) and no
    // empty-payload IPCs are sent, then the only way to get here should be
    // because of `pending_isolated_world_factories`.
    //
    // TODO(crbug.com/40158699): Remove the whole `else` branch once
    // Chrome Platform Apps and `pending_isolated_world_factories` are gone.
    DCHECK(!subresource_loader_factories->pending_isolated_world_factories()
                .empty());

    // `!IsHostChildURLLoaderFactoryBundle` should only happen if the frame
    // hosts a document that isn't related to a real navigation (i.e. if an
    // initial empty document should "inherit" the factories from its
    // opener/parent).
    DCHECK_EQ(NavigationCommitState::kInitialEmptyDocument,
              navigation_commit_state_);

    auto partial_bundle =
        base::MakeRefCounted<blink::ChildURLLoaderFactoryBundle>();
    static_cast<blink::URLLoaderFactoryBundle*>(partial_bundle.get())
        ->Update(std::move(subresource_loader_factories));
    loader_factories_->Update(partial_bundle->PassInterface());
  }

  // Resetting `background_resource_fetch_context_` here so it will be recreated
  // when MaybeGetBackgroundResourceFetchAssets() is called.
  background_resource_fetch_context_.reset();
}

// content::RenderFrame implementation
// ----------------------------------------
const blink::BrowserInterfaceBrokerProxy&
RenderFrameImpl::GetBrowserInterfaceBroker() {
  return frame_->GetBrowserInterfaceBroker();
}

bool RenderFrameImpl::IsPluginHandledExternally(
    const blink::WebElement& plugin_element,
    const blink::WebURL& url,
    const blink::WebString& suggested_mime_type) {
#if BUILDFLAG(ENABLE_PLUGINS)
  return GetContentClient()->renderer()->IsPluginHandledExternally(
      this, plugin_element, GURL(url), suggested_mime_type.Utf8());
#else
  return false;
#endif
}

bool RenderFrameImpl::IsDomStorageDisabled() const {
  return GetContentClient()->renderer()->IsDomStorageDisabled();
}

v8::Local<v8::Object> RenderFrameImpl::GetScriptableObject(
    const blink::WebElement& plugin_element,
    v8::Isolate* isolate) {
#if BUILDFLAG(ENABLE_PLUGINS)

  return GetContentClient()->renderer()->GetScriptableObject(plugin_element,
                                                             isolate);
#else
  return v8::Local<v8::Object>();
#endif
}

void RenderFrameImpl::BindToFrame(blink::WebNavigationControl* frame) {
  DCHECK(!frame_);

  std::pair<FrameMap::iterator, bool> result =
      g_frame_map.Get().emplace(frame, this);
  CHECK(result.second) << "Inserting a duplicate item.";

  frame_ = frame;
}

blink::WebPlugin* RenderFrameImpl::CreatePlugin(
    const blink::WebPluginParams& params) {
  blink::WebPlugin* plugin = nullptr;
  if (GetContentClient()->renderer()->OverrideCreatePlugin(this, params,
                                                           &plugin)) {
    return plugin;
  }
  return nullptr;
}

std::unique_ptr<blink::WebMediaPlayer> RenderFrameImpl::CreateMediaPlayer(
    const blink::WebMediaPlayerSource& source,
    WebMediaPlayerClient* client,
    blink::MediaInspectorContext* inspector_context,
    WebMediaPlayerEncryptedMediaClient* encrypted_client,
    WebContentDecryptionModule* initial_cdm,
    const blink::WebString& sink_id,
    const cc::LayerTreeSettings* settings,
    scoped_refptr<base::TaskRunner> compositor_worker_task_runner) {
  // `settings` should be non-null since the WebView created for
  // RenderFrameImpl always composites.
  DCHECK(settings);
  return media_factory_.CreateMediaPlayer(
      source, client, inspector_context, encrypted_client, initial_cdm, sink_id,
      GetLocalRootWebFrameWidget()->GetFrameSinkId(), *settings,
      agent_scheduling_group_->agent_group_scheduler().CompositorTaskRunner(),
      std::move(compositor_worker_task_runner));
}

std::unique_ptr<blink::WebContentSettingsClient>
RenderFrameImpl::CreateWorkerContentSettingsClient() {
  if (!frame_ || !frame_->View())
    return nullptr;
  return GetContentClient()->renderer()->CreateWorkerContentSettingsClient(
      this);
}

#if !BUILDFLAG(IS_ANDROID)
std::unique_ptr<media::SpeechRecognitionClient>
RenderFrameImpl::CreateSpeechRecognitionClient() {
  if (!frame_ || !frame_->View())
    return nullptr;
  return GetContentClient()->renderer()->CreateSpeechRecognitionClient(this);
}
#endif

scoped_refptr<blink::WebWorkerFetchContext>
RenderFrameImpl::CreateWorkletFetchContext() {
  ServiceWorkerNetworkProviderForFrame* provider =
      static_cast<ServiceWorkerNetworkProviderForFrame*>(
          frame_->GetDocumentLoader()->GetServiceWorkerNetworkProvider());
  DCHECK(provider);

  mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
      watcher_receiver;
  GetWebView()->RegisterRendererPreferenceWatcher(
      watcher_receiver.InitWithNewPipeAndPassRemote());

  mojo::PendingRemote<blink::mojom::ResourceLoadInfoNotifier>
      pending_resource_load_info_notifier;
  resource_load_info_notifier_receivers_.Add(
      this,
      pending_resource_load_info_notifier.InitWithNewPipeAndPassReceiver(),
      agent_scheduling_group_->agent_group_scheduler().DefaultTaskRunner());

  std::vector<std::string> cors_exempt_header_list =
      RenderThreadImpl::current()->cors_exempt_header_list();
  std::vector<blink::WebString> web_cors_exempt_header_list(
      cors_exempt_header_list.size());
  std::ranges::transform(
      cors_exempt_header_list, web_cors_exempt_header_list.begin(),
      [](const auto& header) { return blink::WebString::FromLatin1(header); });

  // `pending_subresource_loader_updater` and
  // `pending_resource_load_info_notifier` are not used for worklets.
  scoped_refptr<blink::WebDedicatedOrSharedWorkerGlobalScopeContext>
      web_dedicated_or_shared_worker_global_scope_context =
          blink::WebDedicatedOrSharedWorkerGlobalScopeContext::Create(
              provider->context(), GetWebView()->GetRendererPreferences(),
              std::move(watcher_receiver), GetLoaderFactoryBundle()->Clone(),
              GetLoaderFactoryBundle()->Clone(),
              /*pending_subresource_loader_updater=*/mojo::NullReceiver(),
              web_cors_exempt_header_list,
              std::move(pending_resource_load_info_notifier));

  web_dedicated_or_shared_worker_global_scope_context->SetAncestorFrameToken(
      frame_->GetLocalFrameToken());
  web_dedicated_or_shared_worker_global_scope_context->set_site_for_cookies(
      frame_->GetDocument().SiteForCookies());
  web_dedicated_or_shared_worker_global_scope_context->set_top_frame_origin(
      frame_->GetDocument().TopFrameOrigin());

  for (auto& observer : observers_) {
    observer.WillCreateWorkerFetchContext(
        web_dedicated_or_shared_worker_global_scope_context.get());
  }
  return web_dedicated_or_shared_worker_global_scope_context;
}

scoped_refptr<blink::WebWorkerFetchContext>
RenderFrameImpl::CreateWorkerFetchContext(
    blink::WebDedicatedWorkerHostFactoryClient* factory_client) {
  DCHECK(factory_client);

  mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
      watcher_receiver;
  GetWebView()->RegisterRendererPreferenceWatcher(
      watcher_receiver.InitWithNewPipeAndPassRemote());

  mojo::PendingRemote<blink::mojom::ResourceLoadInfoNotifier>
      pending_resource_load_info_notifier;
  resource_load_info_notifier_receivers_.Add(
      this,
      pending_resource_load_info_notifier.InitWithNewPipeAndPassReceiver(),
      agent_scheduling_group_->agent_group_scheduler().DefaultTaskRunner());

  scoped_refptr<blink::WebDedicatedOrSharedWorkerGlobalScopeContext>
      web_dedicated_or_shared_worker_global_scope_context =
          static_cast<DedicatedWorkerHostFactoryClient*>(factory_client)
              ->CreateWorkerGlobalScopeContext(
                  GetWebView()->GetRendererPreferences(),
                  std::move(watcher_receiver),
                  std::move(pending_resource_load_info_notifier));

  web_dedicated_or_shared_worker_global_scope_context->SetAncestorFrameToken(
      frame_->GetLocalFrameToken());
  web_dedicated_or_shared_worker_global_scope_context->set_site_for_cookies(
      frame_->GetDocument().SiteForCookies());
  web_dedicated_or_shared_worker_global_scope_context->set_top_frame_origin(
      frame_->GetDocument().TopFrameOrigin());

  for (auto& observer : observers_) {
    observer.WillCreateWorkerFetchContext(
        web_dedicated_or_shared_worker_global_scope_context.get());
  }
  return web_dedicated_or_shared_worker_global_scope_context;
}

std::unique_ptr<blink::WebPrescientNetworking>
RenderFrameImpl::CreatePrescientNetworking() {
  return GetContentClient()->renderer()->CreatePrescientNetworking(this);
}

std::unique_ptr<blink::ResourceLoadInfoNotifierWrapper>
RenderFrameImpl::CreateResourceLoadInfoNotifierWrapper() {
  return std::make_unique<blink::ResourceLoadInfoNotifierWrapper>(
      weak_wrapper_resource_load_info_notifier_->AsWeakPtr(),
      GetTaskRunner(blink::TaskType::kNetworking));
}

std::unique_ptr<blink::WebServiceWorkerProvider>
RenderFrameImpl::CreateServiceWorkerProvider() {
  // Bail-out if we are about to be navigated away.
  // We check that DocumentLoader is attached since:
  // - This serves as the signal since the DocumentLoader is detached in
  //   FrameLoader::PrepareForCommit().
  // - Creating ServiceWorkerProvider in
  //   RenderFrameImpl::CreateServiceWorkerProvider() assumes that there is a
  //   DocumentLoader attached to the frame.
  if (!frame_->GetDocumentLoader())
    return nullptr;

  // At this point we should have non-null data source.
  if (!ChildThreadImpl::current())
    return nullptr;  // May be null in some tests.
  ServiceWorkerNetworkProviderForFrame* provider =
      static_cast<ServiceWorkerNetworkProviderForFrame*>(
          frame_->GetDocumentLoader()->GetServiceWorkerNetworkProvider());
  if (!provider->context()) {
    // The context can be null when the frame is sandboxed.
    return nullptr;
  }
  return std::make_unique<WebServiceWorkerProviderImpl>(provider->context());
}

blink::AssociatedInterfaceProvider*
RenderFrameImpl::GetRemoteNavigationAssociatedInterfaces() {
  return GetRemoteAssociatedInterfaces();
}

namespace {

// Emit the trace event using a helper as we:
// a) want to ensure that the trace event covers the entire function.
// b) we want to emit the new child routing id as an argument.
// c) child routing id becomes available only after a sync call.
struct CreateChildFrameTraceEvent {
  explicit CreateChildFrameTraceEvent(
      const blink::LocalFrameToken& frame_token) {
    TRACE_EVENT_BEGIN("navigation,rail", "RenderFrameImpl::createChildFrame",
                      "frame_token", frame_token);
  }

  ~CreateChildFrameTraceEvent() {
    TRACE_EVENT_END("navigation,rail", "child_frame_token", child_frame_token);
  }

  blink::LocalFrameToken child_frame_token;
};

}  // namespace

blink::WebLocalFrame* RenderFrameImpl::CreateChildFrame(
    blink::mojom::TreeScopeType scope,
    const blink::WebString& name,
    const blink::WebString& fallback_name,
    const blink::FramePolicy& frame_policy,
    const blink::WebFrameOwnerProperties& frame_owner_properties,
    blink::FrameOwnerElementType frame_owner_element_type,
    blink::WebPolicyContainerBindParams policy_container_bind_params,
    ukm::SourceId document_ukm_source_id,
    FinishChildFrameCreationFn finish_creation) {
  // Tracing analysis uses this to find main frames when this value is
  // IPC::mojom::kRoutingIdNone, and build the frame tree otherwise.
  CreateChildFrameTraceEvent trace_event(frame_token_);

  // Allocate child routing ID. This is a synchronous call.
  int child_routing_id;
  blink::LocalFrameToken frame_token;
  base::UnguessableToken devtools_frame_token;
  blink::DocumentToken document_token;
  if (!RenderThread::Get()->GenerateFrameRoutingID(
          child_routing_id, frame_token, devtools_frame_token,
          document_token)) {
    return nullptr;
  }
  trace_event.child_frame_token = frame_token;

  // The unique name generation logic was moved out of Blink, so for historical
  // reasons, unique name generation needs to take something called the
  // |fallback_name| into account. Normally, unique names are generated based on
  // the browsing context name. For new frames, the initial browsing context
  // name comes from the name attribute of the browsing context container
  // element.
  //
  // However, when the browsing context name is null, Blink instead uses the
  // "fallback name" to derive the unique name. The exact contents of the
  // "fallback name" are unspecified, but may contain the value of the
  // 'subresource attribute' of the browsing context container element.
  //
  // Note that Blink can't be changed to just pass |fallback_name| as |name| in
  // the case |name| is empty: |fallback_name| should never affect the actual
  // browsing context name, only unique name generation.
  bool is_created_by_script = GetAgentGroupScheduler().Isolate()->InContext();
  std::string frame_unique_name =
      unique_name_helper_.GenerateNameForNewChildFrame(
          name.IsEmpty() ? fallback_name.Utf8() : name.Utf8(),
          is_created_by_script);

  mojo::PendingAssociatedReceiver<mojom::Frame> pending_frame_receiver;

  mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
      browser_interface_broker;

  mojo::PendingAssociatedRemote<blink::mojom::AssociatedInterfaceProvider>
      associated_interface_provider;

  // Now create the child frame in the browser via an asynchronous call.
  GetFrameHost()->CreateChildFrame(
      frame_token, pending_frame_receiver.InitWithNewEndpointAndPassRemote(),
      browser_interface_broker.InitWithNewPipeAndPassReceiver(),
      blink::mojom::PolicyContainerBindParams::New(
          std::move(policy_container_bind_params.receiver)),
      associated_interface_provider.InitWithNewEndpointAndPassReceiver(), scope,
      name.Utf8(), frame_unique_name, is_created_by_script, frame_policy,
      blink::mojom::FrameOwnerProperties::From(frame_owner_properties),
      frame_owner_element_type, document_ukm_source_id);

  // Create the RenderFrame and WebLocalFrame, linking the two.
  RenderFrameImpl* child_render_frame = RenderFrameImpl::Create(
      *agent_scheduling_group_, frame_token, child_routing_id,
      std::move(pending_frame_receiver),
      std::move(associated_interface_provider), devtools_frame_token,
      /*is_for_nested_main_frame=*/false);
  child_render_frame->SetLoaderFactoryBundle(CloneLoaderFactories());
  child_render_frame->unique_name_helper_.set_propagated_name(
      frame_unique_name);
  if (is_created_by_script)
    child_render_frame->unique_name_helper_.Freeze();
  blink::WebLocalFrame* web_frame = frame_->CreateLocalChild(
      scope, child_render_frame,
      child_render_frame->blink_interface_registry_.get(), frame_token);
  finish_creation(web_frame, document_token,
                  std::move(browser_interface_broker));

  child_render_frame->in_frame_tree_ = true;
  child_render_frame->Initialize(/*parent=*/GetWebFrame());

  return web_frame;
}

void RenderFrameImpl::DidCreateFencedFrame(
    const blink::RemoteFrameToken& frame_token) {
  for (auto& observer : observers_)
    observer.DidCreateFencedFrame(frame_token);
}

blink::WebFrame* RenderFrameImpl::FindFrame(const blink::WebString& name) {
  if (GetBlinkPreferences().renderer_wide_named_frame_lookup) {
    for (const auto& it : g_frame_map.Get()) {
      WebLocalFrame* frame = it.second->GetWebFrame();
      if (frame->AssignedName() == name)
        return frame;
    }
  }

  return GetContentClient()->renderer()->FindFrame(this->GetWebFrame(),
                                                   name.Utf8());
}

void RenderFrameImpl::MaybeInitializeWidget(
    mojom::CreateFrameWidgetParamsPtr widget_params) {
  if (widget_params->reuse_compositor) {
    // Initializing the widget is deferred until commit if this RenderFrame
    // will be replacing a previous RenderFrame. This enables reuse of the
    // compositing setup which is expensive.
    // This step must be deferred until commit since this RenderFrame could be
    // speculative and the previous RenderFrame will continue to be visible
    // and animating until commit.
    //
    // TODO(khushalsagar): Ideal would be to move the widget initialization to
    // the commit stage for all cases. This shouldn't have any perf impact
    // since the expensive parts of compositing (setting up a connection to
    // the GPU process) is not done until the frame is made visible, which
    // happens at commit.
    widget_params_for_lazy_widget_creation_ = std::move(widget_params);
    return;
  }

  InitializeFrameWidgetForFrame(*frame_, /*previous_widget=*/nullptr,
                                std::move(widget_params),
                                is_for_nested_main_frame_);
}

void RenderFrameImpl::InitializeWidgetAtSwap(
    blink::WebLocalFrame& frame_for_compositor_reuse) {
  CHECK(widget_params_for_lazy_widget_creation_);
  DCHECK(widget_params_for_lazy_widget_creation_->reuse_compositor);

  InitializeFrameWidgetForFrame(
      *frame_, frame_for_compositor_reuse.FrameWidget(),
      std::move(widget_params_for_lazy_widget_creation_),
      is_for_nested_main_frame_);
}

void RenderFrameImpl::WillDetach(blink::DetachReason detach_reason) {
  if (detach_reason == blink::DetachReason::kNavigation) {
    if (navigation_client_impl_ &&
        ShouldQueueNavigationsWhenPendingCommitRFHExists()) {
      navigation_client_impl_->ResetWithoutCancelling();
    }

    // If `provisional_frame_for_local_root_swap_` is set by `Swap()`, the
    // widget for the frame being swapped in needs to be initialized now. At
    // this point, the compositor can be passed off safely since the `Document`
    // has already been torn down.
    //
    // TODO(dcheng): This mechanism could probably be used for passing off the
    // unique name as well...
    if (provisional_frame_for_local_root_swap_) {
      CHECK_EQ(
          provisional_frame_for_local_root_swap_->is_for_nested_main_frame_,
          is_for_nested_main_frame_);
      provisional_frame_for_local_root_swap_->InitializeWidgetAtSwap(
          CHECK_DEREF(GetWebFrame()));
      provisional_frame_for_local_root_swap_ = nullptr;
    }
  }

  for (auto& observer : observers_)
    observer.WillDetach(detach_reason);

  // blink::AudioOutputIPCFactory::io_task_runner_ may be null in tests.
  auto& factory = blink::AudioOutputIPCFactory::GetInstance();
  if (factory.io_task_runner())
    factory.MaybeDeregisterRemoteFactory(GetWebFrame()->GetLocalFrameToken());

  // Send a state update before the frame is detached.
  SendUpdateState();
}

void RenderFrameImpl::FrameDetached(blink::DetachReason detach_reason) {
  TRACE_EVENT0("navigation", "RenderFrameImpl::FrameDetached");
  base::ScopedUmaHistogramTimer histogram_timer(
      "Navigation.RenderFrameImpl.FrameDetached");
  // We need to clean up subframes by removing them from the map and deleting
  // the RenderFrameImpl.  In contrast, the main frame is owned by its
  // containing RenderViewHost (so that they have the same lifetime), so only
  // removal from the map is needed and no deletion.
  auto it = g_frame_map.Get().find(frame_);
  CHECK(it != g_frame_map.Get().end());
  CHECK_EQ(it->second, this);
  g_frame_map.Get().erase(it);

  // RenderAccessibilityManager keeps a reference to the RenderFrame that owns
  // it, so we need to clear the pointer to prevent invalid access after the
  // frame gets closed and deleted.
  render_accessibility_manager_.reset();

  // |frame_| may not be referenced after this, so clear the pointer since
  // the actual WebLocalFrame may not be deleted immediately and other methods
  // may try to access it.
  frame_->Close(detach_reason);
  frame_ = nullptr;

  if (mhtml_body_loader_client_) {
    mhtml_body_loader_client_->Detach();
    mhtml_body_loader_client_.reset();
  }

  delete this;
  // Object is invalid after this point.
}

void RenderFrameImpl::DidChangeName(const blink::WebString& name) {
  if (GetWebFrame()->GetCurrentHistoryItem().IsNull()) {
    // Once a navigation has committed, the unique name must no longer change to
    // avoid breaking back/forward navigations: https://crbug.com/607205
    unique_name_helper_.UpdateName(name.Utf8());
  }
  GetFrameHost()->DidChangeName(name.Utf8(), unique_name_helper_.value());
}

void RenderFrameImpl::DidMatchCSS(
    const std::vector<blink::WebString>& newly_matching_selectors,
    const std::vector<blink::WebString>& stopped_matching_selectors) {
  for (auto& observer : observers_)
    observer.DidMatchCSS(newly_matching_selectors, stopped_matching_selectors);
}

bool RenderFrameImpl::ShouldReportDetailedMessageForSourceAndSeverity(
    blink::mojom::ConsoleMessageLevel log_level,
    const blink::WebString& source) {
  if (want_error_message_stack_trace_ &&
      log_level == blink::mojom::ConsoleMessageLevel::kError) {
    return true;
  }
  return GetContentClient()->renderer()->ShouldReportDetailedMessageForSource(
      source.Utf16());
}

void RenderFrameImpl::DidAddMessageToConsole(
    const blink::WebConsoleMessage& message,
    const blink::WebString& source_name,
    unsigned source_line,
    const blink::WebString& stack_trace) {
  if (ShouldReportDetailedMessageForSourceAndSeverity(message.level,
                                                      source_name)) {
    for (auto& observer : observers_) {
      observer.DetailedConsoleMessageAdded(
          message.text.Utf16(), source_name.Utf16(), stack_trace.Utf16(),
          source_line, message.level);
    }
  }
}

void RenderFrameImpl::DidCreateDocumentLoader(
    blink::WebDocumentLoader* document_loader) {
  DocumentState* document_state =
      DocumentState::FromDocumentLoader(document_loader);
  if (!document_state) {
    // This must be an initial empty document.
    document_loader->SetExtraData(BuildDocumentState());
    document_loader->SetServiceWorkerNetworkProvider(
        ServiceWorkerNetworkProviderForFrame::CreateInvalidInstance());
  }

  // Set the code cache host earlier to allow fetching the code cache as soon as
  // possible.
  document_loader->SetCodeCacheHost(
      std::move(pending_code_cache_host_),
      std::move(pending_code_cache_host_for_background_));
}

void RenderFrameImpl::DidCommitNavigation(
    blink::WebHistoryCommitType commit_type,
    bool should_reset_browser_interface_broker,
    const network::ParsedPermissionsPolicy& permissions_policy_header,
    const blink::DocumentPolicyFeatureState& document_policy_header) {
  TRACE_EVENT_WITH_FLOW0("navigation", "RenderFrameImpl::DidCommitNavigation",
                         TRACE_ID_LOCAL(this),
                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  CHECK_EQ(NavigationCommitState::kWillCommit, navigation_commit_state_);
  navigation_commit_state_ = NavigationCommitState::kDidCommit;

  WebDocumentLoader* document_loader = frame_->GetDocumentLoader();
  DocumentState* document_state =
      DocumentState::FromDocumentLoader(document_loader);
  NavigationState* navigation_state = document_state->navigation_state();
  DCHECK(!navigation_state->WasWithinSameDocument());

  TRACE_EVENT2("navigation,benchmark,rail",
               "RenderFrameImpl::didStartProvisionalLoad", "frame_token",
               frame_token_, "url",
               document_loader->GetUrl().GetString().Utf8());

  // Install factories as early as possible - it needs to happen before the
  // newly committed document starts any subresource fetches.  In particular,
  // this needs to happen before invoking
  // RenderFrameObserver::ReadyToCommitNavigation below.
  if (pending_loader_factories_) {
    // Commits triggered by the browser process should always provide
    // |pending_loader_factories_|.
    SetLoaderFactoryBundle(std::move(pending_loader_factories_));
  }
  DCHECK(loader_factories_);
  DCHECK(loader_factories_->HasBoundDefaultFactory());

  // TODO(dgozman): call DidStartNavigation in various places where we call
  // CommitNavigation() on the frame.
  if (!navigation_state->was_initiated_in_this_frame()) {
    // Navigation initiated in this frame has been already reported in
    // BeginNavigation.
    for (auto& observer : observers_)
      observer.DidStartNavigation(document_loader->GetUrl(), std::nullopt);
  }

  for (auto& observer : observers_)
    observer.ReadyToCommitNavigation(document_loader);

  for (auto& observer : observers_)
    observer.DidCreateNewDocument();

  DVLOG(1) << "Committed provisional load: "
           << TrimURL(GetLoadingUrl().possibly_invalid_spec());
  TRACE_EVENT2("navigation,rail", "RenderFrameImpl::didCommitProvisionalLoad",
               "frame_token", frame_token_, "url",
               GetLoadingUrl().possibly_invalid_spec());
  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kWaitForDebuggerOnNavigation)) {
    std::string renderer =
        base::StrCat({"Renderer url=\"",
                      TrimURL(GetLoadingUrl().possibly_invalid_spec()), "\""});
    content::WaitForDebugger(renderer);
  }

  // Generate a new embedding token on each document change.
  GetWebFrame()->SetEmbeddingToken(base::UnguessableToken::Create());

  mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
      browser_interface_broker_receiver;

  // blink passes true when the new pipe needs to be bound.
  if (should_reset_browser_interface_broker) {
    // If we're navigating to a new document, bind
    // |browser_interface_broker_proxy_| to a new browser interface broker. The
    // request end of the new BrowserInterfaceBroker interface will be sent over
    // as part of DidCommitProvisionalLoad. After the RFHI receives the commit
    // confirmation, it will immediately close the old message pipe to avoid
    // GetInterface() calls racing with navigation commit, and bind the request
    // end of the message pipe created here. Must initialize
    // |browser_interface_broker_proxy_| with a new working pipe *before*
    // observers receive DidCommitProvisionalLoad, so they can already request
    // remote interfaces. The interface requests will be serviced once the
    // BrowserInterfaceBroker interface request is bound by the
    // RenderFrameHostImpl.
    browser_interface_broker_receiver =
        frame_->GetBrowserInterfaceBroker().Reset(
            agent_scheduling_group_->agent_group_scheduler()
                .DefaultTaskRunner());

    // blink::AudioOutputIPCFactory::io_task_runner_ may be null in tests.
    auto& factory = blink::AudioOutputIPCFactory::GetInstance();
    if (factory.io_task_runner()) {
      // The RendererAudioOutputStreamFactory must be readily accessible on the
      // IO thread when it's needed, because the main thread may block while
      // waiting for the factory call to finish on the IO thread, so if we tried
      // to lazily initialize it, we could deadlock.
      //
      // TODO(crbug.com/40495144): Still, it is odd for one specific
      // factory to be registered here, make this a RenderFrameObserver.
      // code.
      factory.MaybeDeregisterRemoteFactory(GetWebFrame()->GetLocalFrameToken());
      factory.RegisterRemoteFactory(GetWebFrame()->GetLocalFrameToken(),
                                    frame_->GetBrowserInterfaceBroker());
    }

    // If the request for |audio_input_stream_factory_| is in flight when
    // |browser_interface_broker_proxy_| is reset, it will be silently dropped.
    // We reset |audio_input_stream_factory_| to force a new mojo request to be
    // sent the next time it's used. See https://crbug.com/795258 for
    // implementing a nicer solution.
    audio_input_stream_factory_.reset();

    render_accessibility_manager_->CloseConnection();
  }

  // Notify the MediaPermissionDispatcher that its connection will be closed
  // due to a navigation to a different document.
  if (media_permission_dispatcher_)
    media_permission_dispatcher_->OnNavigation();

  ui::PageTransition transition =
      GetTransitionType(frame_->GetDocumentLoader(), IsMainFrame(),
                        GetWebView()->IsFencedFrameRoot());

  // TODO(crbug.com/40092527): Turn this into a DCHECK for origin equality when
  // the linked bug is fixed. Currently sometimes the browser and renderer
  // disagree on the origin during commit navigation.
  if (pending_cookie_manager_info_ &&
      pending_cookie_manager_info_->origin ==
          url::Origin(frame_->GetDocument().GetSecurityOrigin())) {
    frame_->GetDocument().SetCookieManager(
        std::move(pending_cookie_manager_info_->cookie_manager));
  }

  // TODO(crbug.com/40092527): Turn this into a DCHECK for origin equality when
  // the linked bug is fixed. Currently sometimes the browser and renderer
  // disagree on the origin during commit navigation.
  if (pending_storage_info_ &&
      original_storage_key_.origin() ==
          url::Origin(frame_->GetDocument().GetSecurityOrigin())) {
    if (pending_storage_info_->local_storage_area) {
      frame_->SetLocalStorageArea(
          std::move(pending_storage_info_->local_storage_area));
    }
    if (pending_storage_info_->session_storage_area) {
      frame_->SetSessionStorageArea(
          std::move(pending_storage_info_->session_storage_area));
    }
  }

  DidCommitNavigationInternal(
      commit_type, transition, permissions_policy_header,
      document_policy_header,
      should_reset_browser_interface_broker
          ? mojom::DidCommitProvisionalLoadInterfaceParams::New(
                std::move(browser_interface_broker_receiver))
          : nullptr,
      nullptr /* same_document_params */, GetWebFrame()->GetEmbeddingToken());

  // If we end up reusing this WebRequest (for example, due to a #ref click),
  // we don't want the transition type to persist.  Just clear it.
  navigation_state->set_transition_type(ui::PAGE_TRANSITION_LINK);

  // Check whether we have new encoding name.
  UpdateEncoding(frame_, frame_->View()->PageEncoding().Utf8());

  NotifyObserversOfNavigationCommit(transition);

  document_state->clear_navigation_state();

  ResetMembersUsedForDurationOfCommit();
}

void RenderFrameImpl::DidCommitDocumentReplacementNavigation(
    blink::WebDocumentLoader* document_loader) {
  DocumentState::FromDocumentLoader(document_loader)
      ->set_navigation_state(NavigationState::CreateForSynchronousCommit());
  // TODO(crbug.com/40581836): figure out which of the following observer
  // calls are necessary, if any.
  for (auto& observer : observers_)
    observer.DidStartNavigation(document_loader->GetUrl(), std::nullopt);
  for (auto& observer : observers_)
    observer.ReadyToCommitNavigation(document_loader);
  for (auto& observer : observers_)
    observer.DidCreateNewDocument();
  ui::PageTransition transition = GetTransitionType(
      document_loader, IsMainFrame(), GetWebView()->IsFencedFrameRoot());
  NotifyObserversOfNavigationCommit(transition);
}

void RenderFrameImpl::DidClearWindowObject() {
  TRACE_EVENT_WITH_FLOW0("navigation", "RenderFrameImpl::DidClearWindowObject",
                         TRACE_ID_LOCAL(this),
                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  if (enabled_bindings_.Has(BindingsPolicyValue::kWebUi)) {
    WebUIExtension::Install(frame_);
  }

  const base::CommandLine& command_line =
      *base::CommandLine::ForCurrentProcess();

  // DOM automation bindings that allows the JS content to send JSON-encoded
  // data back to automation in the browser process. By default this isn't
  // allowed unless the process has been started up with the --dom-automation
  // switch.
  if (command_line.HasSwitch(switches::kDomAutomationController))
    DomAutomationController::Install(this, frame_);

  // Bindings that allows the JS content to retrieve a variety of internal
  // metrics. By default this isn't allowed unless the process has been started
  // with the --enable-stats-collection-bindings switch.
  if (command_line.HasSwitch(switches::kStatsCollectionController))
    StatsCollectionController::Install(frame_);

  if (command_line.HasSwitch(switches::kEnableGpuBenchmarking)) {
    GpuBenchmarking::Install(weak_factory_.GetWeakPtr());
  }

  if (command_line.HasSwitch(switches::kEnableSkiaBenchmarking))
    SkiaBenchmarking::Install(frame_);

  for (auto& observer : observers_)
    observer.DidClearWindowObject();
}

void RenderFrameImpl::DidCreateDocumentElement() {
  for (auto& observer : observers_)
    observer.DidCreateDocumentElement();
}

void RenderFrameImpl::RunScriptsAtDocumentElementAvailable() {
  // Wait until any RenderFrameObservers for this frame have a chance to be
  // constructed.
  if (!initialized_)
    return;
  GetContentClient()->renderer()->RunScriptsAtDocumentStart(this);
  // Do not use |this|! ContentClient might have deleted them by now!
}

void RenderFrameImpl::DidReceiveTitle(const blink::WebString& title) {
  // Ignore all but top level navigations.
  if (!frame_->Parent() && !title.IsEmpty()) {
    tracing::TrackNameRecorder::GetInstance()->UpdateProcessLabel(
        process_label_id_, title.Utf8());
  } else {
    // Set process title for sub-frames and title-less frames in traces.
    GURL loading_url = GetLoadingUrl();
    if (!loading_url.host().empty() &&
        loading_url.scheme() != url::kFileScheme) {
      std::string frame_title;
      if (frame_->Parent()) {
        frame_title += "Subframe: ";
      }
      frame_title += loading_url.DeprecatedGetOriginAsURL().spec();
      tracing::TrackNameRecorder::GetInstance()->UpdateProcessLabel(
          process_label_id_, frame_title);
    }
  }

  // Also check whether we have new encoding name.
  UpdateEncoding(frame_, frame_->View()->PageEncoding().Utf8());
}

void RenderFrameImpl::DidDispatchDOMContentLoadedEvent() {
  TRACE_EVENT1("navigation,benchmark,rail",
               "RenderFrameImpl::DidDispatchDOMContentLoadedEvent",
               "frame_token", frame_token_);
  for (auto& observer : observers_)
    observer.DidDispatchDOMContentLoadedEvent();

  // Check whether we have new encoding name.
  UpdateEncoding(frame_, frame_->View()->PageEncoding().Utf8());
}

void RenderFrameImpl::RunScriptsAtDocumentReady() {
  DCHECK(initialized_);
  GetContentClient()->renderer()->RunScriptsAtDocumentEnd(this);
}

void RenderFrameImpl::RunScriptsAtDocumentIdle() {
  GetContentClient()->renderer()->RunScriptsAtDocumentIdle(this);
  // ContentClient might have deleted |this| by now!
}

void RenderFrameImpl::DidHandleOnloadEvents() {
  for (auto& observer : observers_)
    observer.DidHandleOnloadEvents();
}

void RenderFrameImpl::DidFinishLoad() {
  TRACE_EVENT1("navigation,benchmark,rail", "RenderFrameImpl::didFinishLoad",
               "frame_token", frame_token_);
  if (!frame_->Parent()) {
    TRACE_EVENT_INSTANT1("WebCore,benchmark,rail", "LoadFinished",
                         TRACE_EVENT_SCOPE_PROCESS, "isOutermostMainFrame",
                         frame_->IsOutermostMainFrame());
  }

  for (auto& observer : observers_)
    observer.DidFinishLoad();
}

void RenderFrameImpl::DidFinishLoadForPrinting() {
  for (auto& observer : observers_)
    observer.DidFinishLoadForPrinting();
}

void RenderFrameImpl::DidFinishSameDocumentNavigation(
    blink::WebHistoryCommitType commit_type,
    bool is_synchronously_committed,
    blink::mojom::SameDocumentNavigationType same_document_navigation_type,
    bool is_client_redirect,
    const std::optional<blink::SameDocNavigationScreenshotDestinationToken>&
        screenshot_destination) {
  TRACE_EVENT1("navigation,rail",
               "RenderFrameImpl::didFinishSameDocumentNavigation",
               "frame_token", frame_token_);
  WebDocumentLoader* document_loader = frame_->GetDocumentLoader();
  DocumentState* document_state =
      DocumentState::FromDocumentLoader(document_loader);
  if (is_synchronously_committed) {
    document_state->set_navigation_state(
        NavigationState::CreateForSynchronousCommit());
  }
  document_state->navigation_state()->set_was_within_same_document(true);

  ui::PageTransition transition = GetTransitionType(
      document_loader, IsMainFrame(), GetWebView()->IsFencedFrameRoot());
  auto same_document_params =
      mojom::DidCommitSameDocumentNavigationParams::New();
  same_document_params->same_document_navigation_type =
      same_document_navigation_type;
  same_document_params->is_client_redirect = is_client_redirect;
  same_document_params->started_with_transient_activation =
      document_loader->LastNavigationHadTransientUserActivation();
  same_document_params->should_replace_current_entry =
      document_loader->ReplacesCurrentHistoryItem();
  same_document_params->navigation_entry_screenshot_destination =
      screenshot_destination;

  DidCommitNavigationInternal(
      commit_type, transition,
      network::ParsedPermissionsPolicy(),   // permissions_policy_header
      blink::DocumentPolicyFeatureState(),  // document_policy_header
      nullptr,                              // interface_params
      std::move(same_document_params),
      std::nullopt  // embedding_token
  );

  // If we end up reusing this WebRequest (for example, due to a #ref click),
  // we don't want the transition type to persist.  Just clear it.
  document_state->navigation_state()->set_transition_type(
      ui::PAGE_TRANSITION_LINK);

  for (auto& observer : observers_)
    observer.DidFinishSameDocumentNavigation();

  document_state->clear_navigation_state();
}

void RenderFrameImpl::DidFailAsyncSameDocumentCommit() {
  // This is called when the Navigation API deferred a same-document commit,
  // then fails the navigation without committing, so that we can run the
  // callback if this commit was browser-initiated. If the commit is aborted
  // due to frame detach or another navigation preempting it, NavigationState's
  // destructor will run the callback instead.
  DocumentState* document_state =
      DocumentState::FromDocumentLoader(frame_->GetDocumentLoader());
  if (NavigationState* navigation_state = document_state->navigation_state()) {
    navigation_state->RunCommitSameDocumentNavigationCallback(
        blink::mojom::CommitResult::Aborted);
    document_state->clear_navigation_state();
  }
}

void RenderFrameImpl::WillFreezePage() {
  // Make sure browser has the latest info before the page is frozen. If the
  // page goes into the back-forward cache it could be evicted and some of the
  // updates lost.
  SendUpdateState();
}

void RenderFrameImpl::DidOpenDocumentInputStream(const blink::WebURL& url) {
  GURL filtered_url(url);
  if (!IsValidCommitUrl(filtered_url)) {
    filtered_url = GURL(kBlockedURL);
  }
  GetFrameHost()->DidOpenDocumentInputStream(filtered_url);
}

void RenderFrameImpl::DidSetPageLifecycleState(bool restoring_from_bfcache) {
  for (auto& observer : observers_)
    observer.DidSetPageLifecycleState(restoring_from_bfcache);
}

void RenderFrameImpl::NotifyCurrentHistoryItemChanged() {
  SendUpdateState();
}

void RenderFrameImpl::DidUpdateCurrentHistoryItem() {
  StartDelayedSyncTimer();
}

void RenderFrameImpl::StartDelayedSyncTimer() {
  base::TimeDelta delay;
  if (send_content_state_immediately_) {
    SendUpdateState();
    return;
  } else if (GetWebView()->GetVisibilityState() !=
             blink::mojom::PageVisibilityState::kVisible)
    delay = kDelaySecondsForContentStateSyncHidden;
  else
    delay = kDelaySecondsForContentStateSync;

  if (delayed_state_sync_timer_.IsRunning()) {
    // The timer is already running. If the delay of the timer matches the
    // amount we want to delay by, then return. Otherwise stop the timer so that
    // it gets started with the right delay.
    if (delayed_state_sync_timer_.GetCurrentDelay() == delay)
      return;
    delayed_state_sync_timer_.Stop();
  }
  delayed_state_sync_timer_.Start(FROM_HERE, delay, this,
                                  &RenderFrameImpl::SendUpdateState);
}

bool RenderFrameImpl::SwapOutAndDeleteThis(
    bool is_loading,
    blink::mojom::FrameReplicationStatePtr replicated_frame_state,
    const blink::RemoteFrameToken& proxy_frame_token,
    blink::mojom::RemoteFrameInterfacesFromBrowserPtr remote_frame_interfaces,
    blink::mojom::RemoteMainFrameInterfacesPtr remote_main_frame_interfaces,
    const std::optional<base::UnguessableToken>& devtools_frame_token) {
  TRACE_EVENT1("navigation,rail", "RenderFrameImpl::SwapOutAndDeleteThis",
               "frame_token", frame_token_);
  DCHECK(!base::RunLoop::IsNestedOnCurrentThread());

  // Create a WebRemoteFrame so we can pass it into `Swap`.
  blink::WebRemoteFrame* remote_frame = blink::WebRemoteFrame::Create(
      frame_->GetTreeScopeType(), proxy_frame_token);

  blink::WebView* web_view = GetWebView();
  bool is_main_frame = is_main_frame_;

  // The swap call deletes this RenderFrame via FrameDetached.  Do not access
  // any members after this call.
  //
  // TODO(creis): WebFrame::swap() can return false.  Most of those cases
  // should be due to the frame being detached during unload (in which case
  // the necessary cleanup has happened anyway), but it might be possible for
  // it to return false without detaching.
  //
  // This executes the unload handlers on this frame and its local descendants.
  bool success =
      frame_->Swap(remote_frame, std::move(remote_frame_interfaces->frame_host),
                   std::move(remote_frame_interfaces->frame_receiver),
                   std::move(replicated_frame_state), devtools_frame_token);

  // WARNING: Do not access 'this' past this point!

  if (is_main_frame) {
    // Main frames should always swap successfully because there is no parent
    // frame to cause them to become detached.
    DCHECK(success);

    // The `blink::RemoteFrame` being swapped in here has now been attached to
    // the Page as its main frame and properly initialized by the
    // WebFrame::Swap() call, so we can call WebView's
    // DidAttachRemoteMainFrame().
    web_view->DidAttachRemoteMainFrame(
        std::move(remote_main_frame_interfaces->main_frame_host),
        std::move(remote_main_frame_interfaces->main_frame));
  }

  if (!success) {
    // The swap can fail when the frame is detached during swap (this can
    // happen while running the unload handlers). When that happens, delete
    // the proxy.
    remote_frame->Close(blink::DetachReason::kFrameDeletion);
    return false;
  }

  if (is_loading)
    remote_frame->DidStartLoading();

  return true;
}

base::UnguessableToken RenderFrameImpl::GetDevToolsFrameToken() {
  return devtools_frame_token_;
}

void RenderFrameImpl::AbortClientNavigation(bool for_new_navigation) {
  CHECK(in_frame_tree_);

  // If the navigations are deferred, cancellations should be deferred too.
  client_navigation_throttler_.DispatchOrScheduleNavigation(
      base::BindOnce(&RenderFrameImpl::AbortClientNavigationImpl,
                     base::Unretained(this), for_new_navigation));
}

void RenderFrameImpl::AbortClientNavigationImpl(bool for_new_navigation) {
  CHECK(navigation_client_impl_);
  is_requesting_navigation_ = false;
  if (mhtml_body_loader_client_) {
    mhtml_body_loader_client_->Detach();
    mhtml_body_loader_client_.reset();
  }
  NotifyObserversOfFailedProvisionalLoad();
  // See comment in header for more information of how navigation cleanup works.
  // Note: This might not actually cancel the navigation if the navigation is
  // already in the process of committing to a different RenderFrame.
  if (for_new_navigation) {
    navigation_client_impl_->ResetForNewNavigation(
        /*is_duplicate_navigation=*/false);
  } else {
    navigation_client_impl_->ResetForAbort();
  }
  navigation_client_impl_.reset();
}

void RenderFrameImpl::DidChangeSelection(bool is_empty_selection,
                                         blink::SyncCondition force_sync) {
  if (!GetLocalRootWebFrameWidget()->HandlingInputEvent() &&
      !GetLocalRootWebFrameWidget()->HandlingSelectRange())
    return;

  if (is_empty_selection)
    selection_text_.clear();

  // UpdateTextInputState should be called before SyncSelectionIfRequired.
  // UpdateTextInputState may send TextInputStateChanged to notify the focus
  // was changed, and SyncSelectionIfRequired may send SelectionChanged
  // to notify the selection was changed.  Focus change should be notified
  // before selection change.
  GetLocalRootWebFrameWidget()->UpdateTextInputState();
  SyncSelectionIfRequired(force_sync);
}

void RenderFrameImpl::OnMainFrameIntersectionChanged(
    const gfx::Rect& main_frame_intersection_rect) {
  if (main_frame_intersection_rect != main_frame_intersection_rect_) {
    main_frame_intersection_rect_ = main_frame_intersection_rect;
    for (auto& observer : observers_) {
      observer.OnMainFrameIntersectionChanged(main_frame_intersection_rect);
    }
  }
}

void RenderFrameImpl::OnMainFrameViewportRectangleChanged(
    const gfx::Rect& main_frame_viewport_rect) {
  if (main_frame_viewport_rect != main_frame_viewport_rect_) {
    main_frame_viewport_rect_ = main_frame_viewport_rect;
    for (auto& observer : observers_) {
      observer.OnMainFrameViewportRectangleChanged(main_frame_viewport_rect);
    }
  }
}

void RenderFrameImpl::OnMainFrameAdRectangleChanged(int element_id,
                                                    const gfx::Rect& ad_rect) {
  for (auto& observer : observers_) {
    observer.OnMainFrameAdRectangleChanged(element_id, ad_rect);
  }
}

void RenderFrameImpl::OnOverlayPopupAdDetected() {
  for (auto& observer : observers_) {
    observer.OnOverlayPopupAdDetected();
  }
}

void RenderFrameImpl::OnLargeStickyAdDetected() {
  for (auto& observer : observers_) {
    observer.OnLargeStickyAdDetected();
  }
}

void RenderFrameImpl::FinalizeRequest(blink::WebURLRequest& request) {
  // This method is called for subresources, while transition type is
  // a navigation concept. We pass ui::PAGE_TRANSITION_LINK as default one.
  FinalizeRequestInternal(request, /*for_outermost_main_frame=*/false,
                          ui::PAGE_TRANSITION_LINK);
}

std::optional<blink::WebURL> RenderFrameImpl::WillSendRequest(
    const blink::WebURL& target,
    const blink::WebSecurityOrigin& security_origin,
    const net::SiteForCookies& site_for_cookies,
    ForRedirect for_redirect,
    const blink::WebURL& upstream_url) {
  return WillSendRequestInternal(target, security_origin, site_for_cookies,
                                 for_redirect, upstream_url,
                                 ui::PAGE_TRANSITION_LINK);
}

std::optional<blink::WebURL> RenderFrameImpl::WillSendRequestInternal(
    const blink::WebURL& target,
    const blink::WebSecurityOrigin& security_origin,
    const net::SiteForCookies& site_for_cookies,
    ForRedirect for_redirect,
    const blink::WebURL& upstream_url,
    ui::PageTransition transition_type) {
  std::optional<blink::WebURL> adjusted = ApplyFilePathAlias(target);

  GURL new_url;
  std::optional<url::Origin> initiator_origin =
      security_origin.IsNull() ? std::optional<url::Origin>()
                               : std::optional<url::Origin>(security_origin);
  GetContentClient()->renderer()->WillSendRequest(
      frame_, transition_type, upstream_url,
      adjusted.has_value() ? *adjusted : target, site_for_cookies,
      base::OptionalToPtr(initiator_origin), &new_url);
  if (!new_url.is_empty()) {
    return WebURL(new_url);
  }
  return adjusted;
}

void RenderFrameImpl::FinalizeRequestInternal(
    blink::WebURLRequest& request,
    bool for_outermost_main_frame,
    ui::PageTransition transition_type) {
  if (GetWebView()->GetRendererPreferences().enable_do_not_track) {
    request.SetHttpHeaderField(
        blink::WebString::FromUTF8(blink::kDoNotTrackHeader), "1");
  }

  // The request's extra data may indicate that we should set a custom user
  // agent. This needs to be done here, after WebKit is through with setting the
  // user agent on its own.
  WebString custom_user_agent;
  if (request.GetURLRequestExtraData()) {
    blink::WebURLRequestExtraData* old_request_extra_data =
        static_cast<blink::WebURLRequestExtraData*>(
            request.GetURLRequestExtraData().get());

    custom_user_agent = old_request_extra_data->custom_user_agent();
    if (!custom_user_agent.IsNull()) {
      if (custom_user_agent.IsEmpty())
        request.ClearHttpHeaderField("User-Agent");
      else
        request.SetHttpHeaderField("User-Agent", custom_user_agent);
    }
  }

  if (!request.GetURLRequestExtraData()) {
    request.SetURLRequestExtraData(
        base::MakeRefCounted<blink::WebURLRequestExtraData>());
  }
  auto* url_request_extra_data = static_cast<blink::WebURLRequestExtraData*>(
      request.GetURLRequestExtraData().get());
  url_request_extra_data->set_custom_user_agent(custom_user_agent);
  url_request_extra_data->set_is_outermost_main_frame(IsMainFrame() &&
                                                      !IsInFencedFrameTree());
  url_request_extra_data->set_transition_type(transition_type);
  bool is_for_no_state_prefetch =
      GetContentClient()->renderer()->IsPrefetchOnly(this);
  url_request_extra_data->set_is_for_no_state_prefetch(
      is_for_no_state_prefetch);
  url_request_extra_data->set_allow_cross_origin_auth_prompt(
      GetWebView()->GetRendererPreferences().allow_cross_origin_auth_prompt);

  request.SetDownloadToNetworkCacheOnly(is_for_no_state_prefetch &&
                                        !for_outermost_main_frame);

  request.SetHasUserGesture(frame_->HasTransientUserActivation());

  if (!GetWebView()->GetRendererPreferences().enable_referrers) {
    request.SetReferrerString(WebString());
    request.SetReferrerPolicy(network::mojom::ReferrerPolicy::kNever);
  }
}

void RenderFrameImpl::DidLoadResourceFromMemoryCache(
    const blink::WebURLRequest& request,
    const blink::WebURLResponse& response) {
  if (load_from_memory_cache_callback_) {
    load_from_memory_cache_callback_.Run(
        request.Url(), response.RequestId(),
        base::ByteCount(response.EncodedBodyLength()),
        response.MimeType().Utf8(), response.FromArchive());
  } else {
    for (auto& observer : observers_) {
      observer.DidLoadResourceFromMemoryCache(
          request.Url(), response.RequestId(),
          base::ByteCount(response.EncodedBodyLength()),
          response.MimeType().Utf8(), response.FromArchive());
    }
  }
}

void RenderFrameImpl::DidStartResponse(
    const url::SchemeHostPort& final_response_url,
    int request_id,
    network::mojom::URLResponseHeadPtr response_head,
    network::mojom::RequestDestination request_destination,
    bool is_ad_resource) {
  for (auto& observer : observers_) {
    observer.DidStartResponse(final_response_url, request_id, *response_head,
                              request_destination, is_ad_resource);
  }
}

void RenderFrameImpl::DidCompleteResponse(
    int request_id,
    const network::URLLoaderCompletionStatus& status) {
  for (auto& observer : observers_)
    observer.DidCompleteResponse(request_id, status);
}

void RenderFrameImpl::DidCancelResponse(int request_id) {
  for (auto& observer : observers_)
    observer.DidCancelResponse(request_id);
}

void RenderFrameImpl::DidReceiveTransferSizeUpdate(int resource_id,
                                                   int received_data_length) {
  for (auto& observer : observers_) {
    observer.DidReceiveTransferSizeUpdate(
        resource_id, base::ByteCount(received_data_length));
  }
}

void RenderFrameImpl::DidChangePerformanceTiming() {
  for (auto& observer : observers_)
    observer.DidChangePerformanceTiming();
}

void RenderFrameImpl::DidObserveUserInteraction(
    base::TimeTicks max_event_start,
    base::TimeTicks max_event_queued_main_thread,
    base::TimeTicks max_event_commit_finish,
    base::TimeTicks max_event_end,
    uint64_t interaction_offset) {
  for (auto& observer : observers_) {
    observer.DidObserveUserInteraction(
        max_event_start, max_event_queued_main_thread, max_event_commit_finish,
        max_event_end, interaction_offset);
  }
}

void RenderFrameImpl::DidChangeCpuTiming(base::TimeDelta time) {
  for (auto& observer : observers_)
    observer.DidChangeCpuTiming(time);
}

void RenderFrameImpl::DidObserveLoadingBehavior(
    blink::LoadingBehaviorFlag behavior) {
  for (auto& observer : observers_)
    observer.DidObserveLoadingBehavior(behavior);
}

void RenderFrameImpl::DidObserveJavaScriptFrameworks(
    const blink::JavaScriptFrameworkDetectionResult& result) {
  for (auto& observer : observers_) {
    observer.DidObserveJavaScriptFrameworks(result);
  }
}

void RenderFrameImpl::DidObserveSubresourceLoad(
    const blink::SubresourceLoadMetrics& subresource_load_metrics) {
  if (subresource_load_callback_) {
    subresource_load_callback_.Run(subresource_load_metrics);
  } else {
    for (auto& observer : observers_) {
      observer.DidObserveSubresourceLoad(subresource_load_metrics);
    }
  }
}

void RenderFrameImpl::SetNewFeatureUsageCallback(
    NewFeatureUsageCallback callback) {
  new_feature_usage_callback_ = std::move(callback);
}

void RenderFrameImpl::SetSubresourceLoadCallback(
    SubresourceLoadCallback callback) {
  subresource_load_callback_ = std::move(callback);
}

void RenderFrameImpl::SetLoadFromMemoryCacheCallback(
    LoadFromMemoryCacheCallback callback) {
  load_from_memory_cache_callback_ = std::move(callback);
}

void RenderFrameImpl::DidObserveNewFeatureUsage(
    const blink::UseCounterFeature& feature) {
  TRACE_EVENT_WITH_FLOW0("navigation",
                         "RenderFrameImpl::DidObserveNewFeatureUsage",
                         TRACE_ID_LOCAL(this),
                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  if (new_feature_usage_callback_) {
    new_feature_usage_callback_.Run(feature);
  } else {
    for (auto& observer : observers_) {
      observer.DidObserveNewFeatureUsage(feature);
    }
  }
}

void RenderFrameImpl::DidObserveSoftNavigation(
    blink::SoftNavigationMetricsForReporting metrics) {
  for (auto& observer : observers_) {
    observer.DidObserveSoftNavigation(metrics);
  }
}

void RenderFrameImpl::DidObserveLayoutShift(double score,
                                            bool after_input_or_scroll) {
  for (auto& observer : observers_)
    observer.DidObserveLayoutShift(score, after_input_or_scroll);
}

void RenderFrameImpl::DidCreateScriptContext(v8::Local<v8::Context> context,
                                             int world_id) {
  TRACE_EVENT_WITH_FLOW0("navigation",
                         "RenderFrameImpl::DidCreateScriptContext",
                         TRACE_ID_LOCAL(this),
                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  v8::MicrotasksScope microtasks(GetAgentGroupScheduler().Isolate(),
                                 context->GetMicrotaskQueue(),
                                 v8::MicrotasksScope::kDoNotRunMicrotasks);
  if (((enabled_bindings_.Has(BindingsPolicyValue::kMojoWebUi)) ||
       enable_mojo_js_bindings_) &&
      IsMainFrame() && world_id == ISOLATED_WORLD_ID_GLOBAL) {
    // We only allow these bindings to be installed when creating the main
    // world context of the main frame.
    blink::WebV8Features::EnableMojoJS(context, true);

    if (mojo_js_features_) {
      if (mojo_js_features_->file_system_access)
        blink::WebV8Features::EnableMojoJSFileSystemAccessHelper(context, true);
    }
  }

  if (world_id == ISOLATED_WORLD_ID_GLOBAL &&
      mojo_js_interface_broker_.is_valid()) {
    // MojoJS interface broker can be enabled on subframes, and will limit the
    // interfaces JavaScript can request to those provided in the broker.
    blink::WebV8Features::EnableMojoJSAndUseBroker(
        context, std::move(mojo_js_interface_broker_));
  }

  for (auto& observer : observers_)
    observer.DidCreateScriptContext(context, world_id);
}

void RenderFrameImpl::WillReleaseScriptContext(v8::Local<v8::Context> context,
                                               int world_id) {
  for (auto& observer : observers_)
    observer.WillReleaseScriptContext(context, world_id);
}

void RenderFrameImpl::DidChangeScrollOffset() {
  StartDelayedSyncTimer();

  for (auto& observer : observers_)
    observer.DidChangeScrollOffset();
}

blink::WebMediaStreamDeviceObserver*
RenderFrameImpl::MediaStreamDeviceObserver() {
  if (!web_media_stream_device_observer_)
    InitializeMediaStreamDeviceObserver();
  return web_media_stream_device_observer_.get();
}

blink::WebEncryptedMediaClient* RenderFrameImpl::EncryptedMediaClient() {
  return media_factory_.EncryptedMediaClient();
}

blink::WebString RenderFrameImpl::UserAgentOverride() {
  if (ShouldUseUserAgentOverride()) {
    return WebString::FromUTF8(GetWebView()
                                   ->GetRendererPreferences()
                                   .user_agent_override.ua_string_override);
  }

  return blink::WebString();
}

std::optional<blink::UserAgentMetadata>
RenderFrameImpl::UserAgentMetadataOverride() {
  if (ShouldUseUserAgentOverride()) {
    return GetWebView()
        ->GetRendererPreferences()
        .user_agent_override.ua_metadata_override;
  }
  return std::nullopt;
}

bool RenderFrameImpl::ShouldUseUserAgentOverride() const {
  auto* web_view = GetWebView();
  // TODO(nasko): When the top-level frame is remote, there is no
  // WebDocumentLoader associated with it, so the checks below are not valid.
  // Temporarily return early and fix properly as part of
  // https://crbug.com/426555.
  if (web_view->MainFrame()->IsWebRemoteFrame())
    return false;
  const WebLocalFrame* main_frame = web_view->MainFrame()->ToWebLocalFrame();

  WebDocumentLoader* document_loader = main_frame->GetDocumentLoader();
  DocumentState* document_state =
      document_loader ? DocumentState::FromDocumentLoader(document_loader)
                      : nullptr;
  return document_state && document_state->is_overriding_user_agent();
}

blink::mojom::RendererAudioInputStreamFactory*
RenderFrameImpl::GetAudioInputStreamFactory() {
  if (!audio_input_stream_factory_)
    GetBrowserInterfaceBroker().GetInterface(
        audio_input_stream_factory_.BindNewPipeAndPassReceiver(
            agent_scheduling_group_->agent_group_scheduler()
                .DefaultTaskRunner()));
  return audio_input_stream_factory_.get();
}

bool RenderFrameImpl::AllowContentInitiatedDataUrlNavigations(
    const blink::WebURL& url) {
  // Error pages can navigate to data URLs.
  return url.GetString() == kUnreachableWebDataURL;
}

void RenderFrameImpl::PostAccessibilityEvent(const ui::AXEvent& event) {
  if (!IsAccessibilityEnabled())
    return;

  render_accessibility_manager_->GetRenderAccessibilityImpl()->HandleAXEvent(
      event);
}

bool RenderFrameImpl::SendAccessibilitySerialization(
    std::vector<ui::AXTreeUpdate> updates,
    std::vector<ui::AXEvent> events,
    ui::AXLocationAndScrollUpdates location_and_scroll_updates,
    bool had_load_complete_messages) {
  // This function should never be called from a11y unless it's enabled.
  CHECK(IsAccessibilityEnabled());

  return render_accessibility_manager_->GetRenderAccessibilityImpl()
      ->SendAccessibilitySerialization(std::move(updates), std::move(events),
                                       std::move(location_and_scroll_updates),
                                       had_load_complete_messages);
}

void RenderFrameImpl::AddObserver(RenderFrameObserver* observer) {
  observers_.AddObserver(observer);
}

void RenderFrameImpl::RemoveObserver(RenderFrameObserver* observer) {
  observer->RenderFrameGone();
  observers_.RemoveObserver(observer);
}

void RenderFrameImpl::OnDroppedNavigation() {
  is_requesting_navigation_ = false;
  frame_->DidDropNavigation();
}

void RenderFrameImpl::WasHidden() {
  frame_->WasHidden();
  for (auto& observer : observers_)
    observer.WasHidden();
}

void RenderFrameImpl::WasShown() {
  frame_->WasShown();
  for (auto& observer : observers_)
    observer.WasShown();
}

void RenderFrameImpl::OnFrameVisibilityChanged(
    blink::mojom::FrameVisibility render_status) {
  for (auto& observer : observers_) {
    observer.OnFrameVisibilityChanged(render_status);
  }
}

bool RenderFrameImpl::IsMainFrame() {
  return is_main_frame_;
}

bool RenderFrameImpl::IsInFencedFrameTree() const {
  return GetWebFrame()->IsInFencedFrameTree();
}

bool RenderFrameImpl::IsHidden() {
  CHECK(GetWebFrame()->IsProvisional() || GetLocalRootWebFrameWidget())
      << "Only provisional frames are created with no widget";
  if (!GetLocalRootWebFrameWidget()) {
    return true;
  }
  return GetLocalRootWebFrameWidget()->IsHidden();
}

bool RenderFrameImpl::IsLocalRoot() const {
  return !(frame_->Parent() && frame_->Parent()->IsWebLocalFrame());
}

const RenderFrameImpl* RenderFrameImpl::GetLocalRoot() const {
  return IsLocalRoot() ? this
                       : RenderFrameImpl::FromWebFrame(frame_->LocalRoot());
}

base::WeakPtr<RenderFrameImpl> RenderFrameImpl::GetWeakPtr() {
  return weak_factory_.GetWeakPtr();
}

mojom::DidCommitProvisionalLoadParamsPtr
RenderFrameImpl::MakeDidCommitProvisionalLoadParams(
    blink::WebHistoryCommitType commit_type,
    ui::PageTransition transition,
    const network::ParsedPermissionsPolicy& permissions_policy_header,
    const blink::DocumentPolicyFeatureState& document_policy_header,
    const std::optional<base::UnguessableToken>& embedding_token,
    std::optional<blink::PageState> previous_page_state) {
  WebDocumentLoader* document_loader = frame_->GetDocumentLoader();
  const WebURLResponse& response = document_loader->GetWebResponse();

  DocumentState* document_state =
      DocumentState::FromDocumentLoader(frame_->GetDocumentLoader());
  NavigationState* navigation_state = document_state->navigation_state();

  auto params = mojom::DidCommitProvisionalLoadParams::New();
  params->http_status_code = response.HttpStatusCode();
  params->url_is_unreachable = document_loader->HasUnreachableURL();
  params->method = "GET";
  params->post_id = -1;
  params->embedding_token = embedding_token;

  // Pass the navigation token back to the browser process, or generate a new
  // one if this navigation is committing without the browser process asking for
  // it.
  // TODO(clamy): We should add checks on navigations that commit without having
  // been asked to commit by the browser process.
  params->navigation_token = navigation_state->commit_params().navigation_token;
  if (params->navigation_token.is_empty())
    params->navigation_token = base::UnguessableToken::Create();

  // "Standard" commits from Blink create new NavigationEntries. We also treat
  // main frame "inert" commits as creating new NavigationEntries if they
  // replace the current entry on a cross-document navigation (e.g., client
  // redirects, location.replace, navigation to same URL), since this will
  // replace all the subframes and could go cross-origin. We don't want to rely
  // on updating the existing NavigationEntry in this case, since it could leave
  // stale state around.
  params->did_create_new_entry =
      (commit_type == blink::kWebStandardCommit) ||
      (commit_type == blink::kWebHistoryInertCommit && !frame_->Parent() &&
       document_loader->ReplacesCurrentHistoryItem() &&
       !navigation_state->WasWithinSameDocument());

  WebDocument frame_document = frame_->GetDocument();
  // Set the origin of the frame.  This will be replicated to the corresponding
  // RenderFrameProxies in other processes.
  WebSecurityOrigin frame_origin = frame_document.GetSecurityOrigin();
  params->origin = frame_origin;

  params->permissions_policy_header = permissions_policy_header;
  params->document_policy_header = document_policy_header;

  params->insecure_request_policy = frame_->GetInsecureRequestPolicy();
  params->insecure_navigations_set = frame_->GetInsecureRequestToUpgrade();

  params->has_potentially_trustworthy_unique_origin =
      frame_origin.IsOpaque() && frame_origin.IsPotentiallyTrustworthy();

  // Set the URL to be displayed in the browser UI to the user. Note this might
  // be different than the URL actually used in the DocumentLoader (see comments
  // in GetLoadingUrl() and MaybeGetOverriddenURL()). This might not be the URL
  // actually shown to the user as well, since the browser has additional logic
  // for virtual URLs (e.g. the "history URL" is shown for loadDataWithBaseURL
  // instead of this URL).
  params->url = GetLoadingUrl();
  // Note: since we get the security origin from the `frame_document`, we also
  // get the base url from it too.
  if (params->url.IsAboutBlank() || params->url.IsAboutSrcdoc()) {
    GURL base_url = frame_document.BaseURL();
    // Only pass the base URL if it is valid and can be serialized by Mojo.
    if (base_url.is_valid() &&
        base_url.possibly_invalid_spec().length() <= url::kMaxURLChars) {
      params->initiator_base_url = base_url;
    }
  }

  // Don't send commit URLs to the browser that are known to be unsupported
  // (e.g., would not pass RenderProcessHostImpl::FilterURL). This is applied
  // after the initiator_base_url check above to avoid passing a base URL when
  // the URL was not about:blank but was rewritten to about:blank#blocked.
  if (!IsValidCommitUrl(params->url)) {
    params->url = GURL(kBlockedURL);
  }

  // When `history::kVisitedLinksOn404` is enabled, visits to reachable URLs
  // that have a 404 status code qualify for history updates. Otherwise, we
  // shouldn't update history for 404s.
  bool does_status_code_qualify_for_history =
      base::FeatureList::IsEnabled(history::kVisitedLinksOn404) ||
      response.HttpStatusCode() != 404;
  // TODO(crbug.com/40161149): Reconsider how we calculate
  // should_update_history.
  params->should_update_history = !document_loader->HasUnreachableURL() &&
                                  does_status_code_qualify_for_history;

  if (previous_page_state.has_value()) {
    params->previous_page_state = previous_page_state;
  }

  // Make navigation state a part of the DidCommitProvisionalLoad message so
  // that committed entry has it at all times.  Send a single HistoryItem for
  // this frame, rather than the whole tree.  It will be stored in the
  // corresponding FrameNavigationEntry.
  const WebHistoryItem& item = GetWebFrame()->GetCurrentHistoryItem();
  params->page_state = GetWebFrame()->CurrentHistoryItemToPageState();

  params->method = document_loader->HttpMethod().Latin1();
  if (params->method == "POST")
    params->post_id = ExtractPostId(item);

  params->item_sequence_number = item.ItemSequenceNumber();
  params->document_sequence_number = item.DocumentSequenceNumber();
  params->navigation_api_key = item.GetNavigationApiKey().Utf8();

  // Note that the value of `referrer` will be overwritten in the browser with a
  // browser-calculated value in most cases. The exceptions are
  // renderer-initated same-document navigations and the synchronous about:blank
  // commit (because the browser doesn't know anything about those navigations).
  // In those cases, the referrer policy component will still be overwritten in
  // the browser, because this navigation won't change it and the browser
  // already had access to the previous one. Send ReferrerPolicy::kDefault as a
  // placeholder.
  // TODO(crbug.com/40150370): Remove `referrer` from
  // DidCommitProvisionalLoadParams.
  params->referrer = blink::mojom::Referrer::New(
      blink::WebStringToGURL(document_loader->Referrer()),
      network::mojom::ReferrerPolicy::kDefault);

  if (!frame_->Parent()) {
    // Top-level navigation.

    // Update contents MIME type for main frame.
    params->contents_mime_type =
        document_loader->GetWebResponse().MimeType().Utf8();

    params->transition = transition;
    // Check that if we are in a fenced frame tree then we must have
    // PAGE_TRANSITION_AUTO_SUBFRAME. Otherwise we are a main frame
    // and should have valid main frame values.
    if (GetWebView()->IsFencedFrameRoot()) {
      DCHECK(ui::PageTransitionCoreTypeIs(params->transition,
                                          ui::PAGE_TRANSITION_AUTO_SUBFRAME));
    } else {
      DCHECK(ui::PageTransitionIsMainFrame(params->transition));
    }

    // If the page contained a client redirect (meta refresh, document.loc...),
    // set the transition appropriately.
    if (document_loader->IsClientRedirect()) {
      params->transition = ui::PageTransitionFromInt(
          params->transition | ui::PAGE_TRANSITION_CLIENT_REDIRECT);
    }

    // Send the user agent override back.
    params->is_overriding_user_agent =
        document_state->is_overriding_user_agent();

    params->history_list_was_cleared =
        navigation_state->commit_params().should_clear_history_list;
  } else {
    // Subframe navigation: the type depends on whether this navigation
    // generated a new session history entry. When they do generate a session
    // history entry, it means the user initiated the navigation and we should
    // mark it as such.
    if (commit_type == blink::kWebStandardCommit)
      params->transition = ui::PAGE_TRANSITION_MANUAL_SUBFRAME;
    else
      params->transition = ui::PAGE_TRANSITION_AUTO_SUBFRAME;

    DCHECK(!navigation_state->commit_params().should_clear_history_list);
    params->history_list_was_cleared = false;
  }

  bool requires_universal_access = false;
  const bool file_scheme_with_universal_access =
      params->origin.scheme() == url::kFileScheme &&
      GetBlinkPreferences().allow_universal_access_from_file_urls;

  // Standard URLs must match the reported origin, when it is not unique.
  // This check is very similar to RenderFrameHostImpl::CanCommitOrigin, but
  // adapted to the renderer process side.
  if (!params->origin.opaque() && params->url.IsStandard() &&
      GetBlinkPreferences().web_security_enabled) {
    if (!params->origin.IsSameOriginWith(params->url)) {
      // Exclude file: URLs when settings allow them access any origin.
      if (!file_scheme_with_universal_access) {
        SCOPED_CRASH_KEY_STRING256("MakeDCPLParams", "mismatched_url",
                                   params->url.possibly_invalid_spec());
        SCOPED_CRASH_KEY_STRING256("MakeDCPLParams", "mismatched_origin",
                                   params->origin.GetDebugString());
        NOTREACHED() << " url:" << params->url << " origin:" << params->origin;
      } else {
        requires_universal_access = true;
      }
    }
    if (file_scheme_with_universal_access) {
      base::UmaHistogramBoolean(
          "Android.WebView.UniversalAccess.OriginUrlMismatchInRenderFrame",
          requires_universal_access);
    }
  }
  params->request_id = document_state->request_id();

  params->unload_start =
      GetWebFrame()->PerformanceMetricsForNestedContexts().UnloadStart();
  params->unload_end =
      GetWebFrame()->PerformanceMetricsForNestedContexts().UnloadEnd();
  params->commit_navigation_start = navigation_state->commit_start_time();
  params->commit_navigation_end = GetWebFrame()
                                      ->PerformanceMetricsForNestedContexts()
                                      .CommitNavigationEnd();
  // Note: this value should be recorded close to sending the DidCommit IPC.
  params->commit_reply_sent = base::TimeTicks().Now();

  return params;
}

void RenderFrameImpl::UpdateNavigationHistory(
    blink::WebHistoryCommitType commit_type) {
  NavigationState* navigation_state =
      DocumentState::FromDocumentLoader(frame_->GetDocumentLoader())
          ->navigation_state();
  const blink::mojom::CommitNavigationParams& commit_params =
      navigation_state->commit_params();

  GetWebFrame()->UpdateCurrentHistoryItem();
  GetWebFrame()->SetTargetToCurrentHistoryItem(
      blink::WebString::FromUTF8(unique_name_helper_.value()));

  bool is_new_navigation = commit_type == blink::kWebStandardCommit;
  blink::WebView* webview = GetWebView();
  if (commit_params.should_clear_history_list) {
    webview->SetHistoryListFromNavigation(/*history_index*/ 0,
                                          /*history_length*/ 1);
  } else if (is_new_navigation) {
    DCHECK(!navigation_state->common_params().should_replace_current_entry ||
           (webview->HistoryBackListCount() +
            webview->HistoryForwardListCount() + 1) > 0);
    if (!navigation_state->common_params().should_replace_current_entry)
      webview->IncreaseHistoryListFromNavigation();
  } else if (commit_params.nav_entry_id != 0 &&
             !commit_params.intended_as_new_entry) {
    webview->SetHistoryListFromNavigation(
        navigation_state->commit_params().pending_history_list_index, {});
  }
}

void RenderFrameImpl::NotifyObserversOfNavigationCommit(
    ui::PageTransition transition) {
  TRACE_EVENT_WITH_FLOW0("navigation",
                         "RenderFrameImpl::NotifyObserversOfNavigationCommit",
                         TRACE_ID_LOCAL(this),
                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  for (auto& observer : observers_)
    observer.DidCommitProvisionalLoad(transition);
}

void RenderFrameImpl::UpdateStateForCommit(
    blink::WebHistoryCommitType commit_type,
    ui::PageTransition transition) {
  DocumentState* document_state =
      DocumentState::FromDocumentLoader(frame_->GetDocumentLoader());
  NavigationState* navigation_state = document_state->navigation_state();

  if (!base::FeatureList::IsEnabled(kReducePageStateIpcs)) {
    // We need to update the last committed session history entry with state for
    // the previous page. Do this before updating the current history item.
    SendUpdateState();
  }

  UpdateNavigationHistory(commit_type);

  if (!frame_->Parent()) {  // Only for top frames.
    RenderThreadImpl* render_thread_impl = RenderThreadImpl::current();
    if (render_thread_impl) {  // Can be NULL in tests.
      render_thread_impl->histogram_customizer()->RenderViewNavigatedToHost(
          GetLoadingUrl().host(), blink::WebView::GetWebViewCount());
    }
  }

  if (IsLocalRoot()) {
    // This forces zoom factor to be propagated to the blink core frame.
    auto& widget = CHECK_DEREF(GetLocalRootWebFrameWidget());
    widget.SetZoomLevel(widget.GetZoomLevel());
  }

  // If we are a top frame navigation to another document we should clear any
  // existing autoplay flags on the Page. This is because flags are stored at
  // the page level so subframes would only add to them.
  if (!frame_->Parent() && !navigation_state->WasWithinSameDocument()) {
    GetWebView()->ClearAutoplayFlags();
  }

  // Set the correct autoplay flags on the Page and wipe the cached origin so
  // this will not be used incorrectly.
  if (url::Origin(frame_->GetSecurityOrigin()) == autoplay_flags_.first) {
    GetWebView()->AddAutoplayFlags(autoplay_flags_.second);
    autoplay_flags_.first = url::Origin();
  }
}

void RenderFrameImpl::DidCommitNavigationInternal(
    blink::WebHistoryCommitType commit_type,
    ui::PageTransition transition,
    const network::ParsedPermissionsPolicy& permissions_policy_header,
    const blink::DocumentPolicyFeatureState& document_policy_header,
    mojom::DidCommitProvisionalLoadInterfaceParamsPtr interface_params,
    mojom::DidCommitSameDocumentNavigationParamsPtr same_document_params,
    const std::optional<base::UnguessableToken>& embedding_token) {
  DCHECK(!(same_document_params && interface_params));

  // The pre-navigation page state needs to be saved before
  // UpdateStateForCommit() since that call will update the current history
  // item.
  std::optional<blink::PageState> previous_page_state = std::nullopt;
  if (base::FeatureList::IsEnabled(kReducePageStateIpcs) &&
      !GetWebFrame()->GetCurrentHistoryItem().IsNull()) {
    previous_page_state = GetWebFrame()->CurrentHistoryItemToPageState();
  }
  UpdateStateForCommit(commit_type, transition);

  if (GetBlinkPreferences().renderer_wide_named_frame_lookup)
    GetWebFrame()->SetAllowsCrossBrowsingInstanceFrameLookup();

  auto params = MakeDidCommitProvisionalLoadParams(
      commit_type, transition, permissions_policy_header,
      document_policy_header, embedding_token, previous_page_state);
  NavigationState* navigation_state =
      DocumentState::FromDocumentLoader(frame_->GetDocumentLoader())
          ->navigation_state();

  // This invocation must precede any calls to allowScripts(), allowImages(),
  // or allowPlugins() for the new page. This ensures that when these functions
  // call chrome::ContentSettingsManager::OnContentBlocked, those calls arrive
  // after the browser process has already been informed of the provisional
  // load committing.
  if (same_document_params) {
    GetFrameHost()->DidCommitSameDocumentNavigation(
        std::move(params), std::move(same_document_params));
    // This will be a noop if this same document navigation is a synchronous
    // renderer-initiated commit.
    navigation_state->RunCommitSameDocumentNavigationCallback(
        blink::mojom::CommitResult::Ok);
  } else {
    if (navigation_state->has_navigation_client()) {
      navigation_state->RunCommitNavigationCallback(
          std::move(params), std::move(interface_params));
    } else {
      GetFrameHost()->DidCommitProvisionalLoad(std::move(params),
                                               std::move(interface_params));
    }
  }

  // Ensure we will propagate the main frame and viewport rect when the main
  // frame commits even if the rect does not change across navigations.
  if (IsMainFrame()) {
    main_frame_intersection_rect_.reset();
    main_frame_viewport_rect_.reset();
  }

  // Record metrics and trace events for the navigation that was just committed.
  // For the navigation start time, use `actual_navigation_start` from
  // common_params() instead of `navigation_start`, since the latter might've
  // been adjusted by beforeunload handling, and it's important to use the
  // non-adjusted version for trace events.
  RendererNavigationMetricsManager::Instance().ProcessNavigationCommit(
      navigation_state->commit_params().navigation_metrics_token,
      navigation_state->common_params().url,
      navigation_state->common_params().actual_navigation_start,
      navigation_state->commit_params().commit_sent, IsMainFrame());
  // Add any new code above the ProcessNavigationCommit call.
}

void RenderFrameImpl::PrepareFrameForCommit(
    const GURL& url,
    const blink::mojom::CommitNavigationParams& commit_params) {
  is_requesting_navigation_ = false;
  GetContentClient()->SetActiveURL(
      url, frame_->Top()->GetSecurityOrigin().ToString().Utf8());

  GetWebView()->SetHistoryListFromNavigation(
      commit_params.current_history_list_index,
      commit_params.current_history_list_length);
}

blink::mojom::CommitResult RenderFrameImpl::PrepareForHistoryNavigationCommit(
    const blink::mojom::CommonNavigationParams& common_params,
    const blink::mojom::CommitNavigationParams& commit_params,
    WebHistoryItem* item_for_history_navigation,
    blink::WebFrameLoadType* load_type) {
  blink::mojom::NavigationType navigation_type = common_params.navigation_type;
  DCHECK(navigation_type ==
             blink::mojom::NavigationType::HISTORY_SAME_DOCUMENT ||
         navigation_type ==
             blink::mojom::NavigationType::HISTORY_DIFFERENT_DOCUMENT ||
         navigation_type == blink::mojom::NavigationType::RESTORE ||
         navigation_type == blink::mojom::NavigationType::RESTORE_WITH_POST);
  *item_for_history_navigation = WebHistoryItem(
      blink::PageState::CreateFromEncodedData(commit_params.page_state));
  if (item_for_history_navigation->IsNull())
    return blink::mojom::CommitResult::Aborted;

  // The browser process sends a single WebHistoryItem for this frame.
  // TODO(creis): Change PageState to FrameState.  In the meantime, we
  // store the relevant frame's WebHistoryItem in the root of the
  // PageState.
  if (navigation_type == blink::mojom::NavigationType::HISTORY_SAME_DOCUMENT ||
      navigation_type ==
          blink::mojom::NavigationType::HISTORY_DIFFERENT_DOCUMENT) {
    *load_type = blink::WebFrameLoadType::kBackForward;
  } else {
    *load_type = blink::WebFrameLoadType::kRestore;
  }

  // Keep track of which subframes the browser process has history items
  // for during a history navigation.
  history_subframe_unique_names_ = commit_params.subframe_unique_names;

  if (navigation_type == blink::mojom::NavigationType::HISTORY_SAME_DOCUMENT) {
    // If this is marked as a same document load but we haven't committed
    // anything, we can't proceed with the load. The browser shouldn't let this
    // happen.
    // TODO(crbug.com/41489044): A same-document history navigation was
    // performed but the renderer does not have a history item. Diagnose this,
    // make it a CHECK again, and drop the Restart.
    DCHECK(!GetWebFrame()->GetCurrentHistoryItem().IsNull());
    if (GetWebFrame()->GetCurrentHistoryItem().IsNull()) {
      SCOPED_CRASH_KEY_BOOL("history_no_item", "is_main_frame", IsMainFrame());
      SCOPED_CRASH_KEY_NUMBER("history_no_item", "renderer_commit_state",
                              (int)navigation_commit_state_);
      SCOPED_CRASH_KEY_NUMBER("history_no_item", "browser_history_index",
                              commit_params.current_history_list_index);
      SCOPED_CRASH_KEY_NUMBER("history_no_item", "browser_history_len",
                              commit_params.current_history_list_length);
      SCOPED_CRASH_KEY_NUMBER("history_no_item", "renderer_history_len",
                              GetWebView()->HistoryBackListCount() +
                                  GetWebView()->HistoryForwardListCount() + 1);
      base::debug::DumpWithoutCrashing();
      return blink::mojom::CommitResult::RestartCrossDocument;
    }

    // Additionally, if the current history item's document sequence number
    // doesn't match the one sent from the browser, it is possible that this
    // renderer has committed a different document. In such case, the navigation
    // cannot be loaded as a same-document navigation. The browser shouldn't let
    // this happen.
    // TODO(crbug.com/40055210): A same document history navigation was
    // performed but the renderer thinks there's a different document loaded.
    // Where did this bad state of a different document + same-document
    // navigation come from? Figure it out, make this a CHECK again, and drop
    // the Restart.
    DCHECK_EQ(GetWebFrame()->GetCurrentHistoryItem().DocumentSequenceNumber(),
              item_for_history_navigation->DocumentSequenceNumber());
    if (GetWebFrame()->GetCurrentHistoryItem().DocumentSequenceNumber() !=
        item_for_history_navigation->DocumentSequenceNumber()) {
      SCOPED_CRASH_KEY_NUMBER(
          "history_bad_seq", "browser_doc_seq_num",
          item_for_history_navigation->DocumentSequenceNumber());
      SCOPED_CRASH_KEY_NUMBER(
          "history_bad_seq", "renderer_doc_seq_num",
          GetWebFrame()->GetCurrentHistoryItem().DocumentSequenceNumber());
      base::debug::DumpWithoutCrashing();
      return blink::mojom::CommitResult::RestartCrossDocument;
    }
  }

  // Note: we used to check that initial history navigation in the child frame
  // was not canceled by a client redirect before committing it. However,
  // we now destroy the NavigationClient for initial history navigation, and
  // commit does not arrive to the renderer in this case.

  return blink::mojom::CommitResult::Ok;
}

bool RenderFrameImpl::SwapIn(WebFrame* previous_web_frame) {
  CHECK(!in_frame_tree_);

  // The unique name can still change in `WebFrame::Swap()` below (due to JS
  // changing the browsing context name), but in practice, this seems to be good
  // enough.
  unique_name_helper_.set_propagated_name(
      GetUniqueNameOfWebFrame(previous_web_frame));

  // Swapping out a frame can dispatch JS event handlers, causing `this` to be
  // deleted.
  bool is_main_frame = is_main_frame_;
  if (auto* render_frame = RenderFrameImpl::FromWebFrame(previous_web_frame);
      render_frame && widget_params_for_lazy_widget_creation_) {
    // For local -> local swaps that lazily initialize the widget, tell the
    // previous RenderFrame (i.e. the frame being swapped out) about `this`
    // (i.e. the frame being swapped in), so `WillDetach()` on the previous
    // RenderFrame can pass off its compositor to `this` for reuse.
    //
    // TODO(dcheng): Blink should already know the provisional frame internally;
    // consider exposing that through the public API to avoid having to plumb
    // state at a distance like this.
    render_frame->provisional_frame_for_local_root_swap_ = GetWeakPtr();
  }
  if (!previous_web_frame->Swap(frame_)) {
    // Main frames should always swap successfully because there is no parent
    // frame to cause them to become detached.
    DCHECK(!is_main_frame);
    return false;
  }

  // For local roots, whether the frame widget is created eagerly or lazily, it
  // must be initialized by this point.
  //
  // For non local roots, they must have a local root ancestor which already has
  // a frame widget.
  CHECK(GetLocalRootWebFrameWidget());

  // `previous_web_frame` is now detached, and should no longer be referenced.

  in_frame_tree_ = true;

  // If this is the main frame going from a remote frame to a local frame,
  // it needs to set RenderViewImpl's pointer for the main frame to itself.
  if (is_main_frame_) {
    // The WebFrame being swapped in here has now been attached to the Page as
    // its main frame, and the WebFrameWidget was previously initialized when
    // the frame was created so we can call WebView's DidAttachLocalMainFrame().
    GetWebView()->DidAttachLocalMainFrame();
  }

  return true;
}

void RenderFrameImpl::DidStartLoading() {
  // TODO(dgozman): consider removing this callback.
  TRACE_EVENT1("navigation,rail", "RenderFrameImpl::didStartLoading",
               "frame_token", frame_token_);
}

void RenderFrameImpl::DidStopLoading() {
  TRACE_EVENT1("navigation,rail", "RenderFrameImpl::didStopLoading",
               "frame_token", frame_token_);

  // Any subframes created after this point won't be considered part of the
  // current history navigation (if this was one), so we don't need to track
  // this state anymore.
  history_subframe_unique_names_.clear();

  GetFrameHost()->DidStopLoading();
}

void RenderFrameImpl::NotifyAccessibilityModeChange(ui::AXMode new_mode) {
  for (auto& observer : observers_)
    observer.AccessibilityModeChanged(new_mode);
}

void RenderFrameImpl::FocusedElementChanged(const blink::WebElement& element) {
  for (auto& observer : observers_)
    observer.FocusedElementChanged(element);
}

void RenderFrameImpl::BeginNavigation(
    std::unique_ptr<blink::WebNavigationInfo> info) {
  // A provisional frame should never make a renderer-initiated navigation: no
  // JS should be running in |this|, and no other frame should have a reference
  // to |this|.
  CHECK(in_frame_tree_);

  // This might be the first navigation in this RenderFrame.
  const bool first_navigation_in_render_frame = !had_started_any_navigation_;
  had_started_any_navigation_ = true;

  // This method is only called for renderer initiated navigations, which
  // may have originated from a link-click, script, drag-n-drop operation, etc.

  // Note that we don't want to go to browser for a navigation to an empty url,
  // which happens for window.open('') call. An example would be embedder
  // deciding to fork the process for the empty url, or setting
  // |browser_handles_all_top_level_requests| preference.
  //
  // Doing a browser-side navigation might later trigger unload handlers,
  // e.g. when the dom window of the popup has already been touched
  // synchronously in this process. We should avoid that.
  //
  // See the checks for empty url in the cases below.
  // TODO(dgozman): if we rewrite empty url to about:blank earlier
  // (we currently do that in DocumentLoader), all the empty checks can be
  // removed, since they already account for an empty url.

  const GURL& url = info->url_request.Url();
  TRACE_EVENT2("navigation", "RenderFrameImpl::BeginNavigation", "url",
               url.possibly_invalid_spec(), "navigation_type",
               static_cast<int>(info->navigation_type));

  // When an MHTML Archive is present, it should be used to serve iframe
  // content instead of doing a network request. This should never be true for
  // the main frame.
  bool use_archive = (info->archive_status ==
                      blink::WebNavigationInfo::ArchiveStatus::Present) &&
                     !url.SchemeIs(url::kDataScheme);
  DCHECK(!(use_archive && IsMainFrame()));

#if BUILDFLAG(IS_ANDROID)
  // The handlenavigation API is deprecated and will be removed once
  // crbug.com/325351 is resolved.
  if (!url.is_empty() && !use_archive && !IsURLHandledByNetworkStack(url) &&
      GetContentClient()->renderer()->HandleNavigation(
          this, frame_, info->url_request, info->navigation_type,
          info->navigation_policy, false /* is_redirect */)) {
    return;
  }
#endif

  // TODO(crbug.com/40221940): Refactor _unfencedTop handling.
  if (info->is_unfenced_top_navigation) {
    OpenURL(std::move(info));
    return;
  }

  // If the browser is interested, then give it a chance to look at the request.
  if (IsTopLevelNavigation(frame_) &&
      GetWebView()
          ->GetRendererPreferences()
          .browser_handles_all_top_level_requests) {
    OpenURL(std::move(info));
    return;  // Suppress the load here.
  }

  // Back/forward navigations in newly created subframes should be sent to the
  // browser if there is a matching FrameNavigationEntry, and if it isn't just
  // staying at about:blank.  If this frame isn't in the map of unique names
  // that have history items, or if it's staying at the initial about:blank URL,
  // fall back to loading the default url.  (We remove each name as we encounter
  // it, because it will only be used once as the frame is created.)
  // Note: Skip this logic for MHTML files (|use_archive|), which should load
  // their subframes from the archive and not from history.
  bool is_history_navigation_in_new_child_frame = false;
  if (info->is_history_navigation_in_new_child_frame && frame_->Parent() &&
      !use_archive) {
    // Check whether the browser has a history item for this frame that isn't
    // just staying at the initial about:blank document.
    RenderFrameImpl* parent = RenderFrameImpl::FromWebFrame(frame_->Parent());
    auto iter = parent->history_subframe_unique_names_.find(
        unique_name_helper_.value());
    if (iter != parent->history_subframe_unique_names_.end()) {
      bool history_item_is_about_blank = iter->second;
      is_history_navigation_in_new_child_frame =
          !history_item_is_about_blank || url != url::kAboutBlankURL;
      parent->history_subframe_unique_names_.erase(iter);
    }
  }

  if (is_history_navigation_in_new_child_frame) {
    // Don't do this if |info| also says it is a client redirect, in which
    // case JavaScript on the page is trying to interrupt the history
    // navigation.
    if (info->is_client_redirect) {
      // Client redirects during an initial history load should attempt to
      // cancel the history navigation.  They will create a provisional
      // document loader, causing the history load to be ignored in
      // NavigateInternal, and this IPC will try to cancel any cross-process
      // history load.
      is_history_navigation_in_new_child_frame = false;
      GetFrameHost()->CancelInitialHistoryLoad();
    }
  }

  // Use the frame's original request's URL rather than the document's URL for
  // subsequent checks.  For a popup, the document's URL may become the opener
  // window's URL if the opener has called document.write().
  // See http://crbug.com/93517.
  GURL old_url(frame_->GetDocumentLoader()->GetUrl());

  // Detect when we're crossing a permission-based boundary (e.g. into or out of
  // an extension or app origin, leaving a WebUI page, etc). We only care about
  // top-level navigations (not iframes). But we sometimes navigate to
  // about:blank to clear a tab, and we want to still allow that.
  if (IsTopLevelNavigation(frame_) && !url.SchemeIs(url::kAboutScheme) &&
      !url.is_empty()) {
    // All navigations to or from WebUI URLs or within WebUI-enabled
    // RenderProcesses must be handled by the browser process so that the
    // correct bindings and data sources can be registered.
    // All frames in a WebUI process must have the same enabled_bindings_, so
    // we can do a per-frame check here rather than a process-wide check.
    bool should_fork = HasWebUIScheme(url) || HasWebUIScheme(old_url) ||
                       enabled_bindings_.HasAny(kWebUIBindingsPolicySet);
    if (should_fork) {
      OpenURL(std::move(info));
      return;  // Suppress the load here.
    }
  }

  if (frame_->IsOutermostMainFrame() && url.is_valid() &&
      url.SchemeIsHTTPOrHTTPS() &&
      (base::FeatureList::IsEnabled(
           blink::features::kHttpDiskCachePrewarming) ||
       base::FeatureList::IsEnabled(
           blink::features::kSpeculativeServiceWorkerWarmUp))) {
    frame_->MaybeStartOutermostMainFrameNavigation(std::vector<WebURL>({url}));
  }

  // Depending on navigation policy, send one of three IPCs to the browser
  // process: DownloadURL handles downloads, OpenURL handles all navigations
  // that will end up in a different tab/window, and BeginNavigation handles
  // everything else.
  if (info->navigation_policy == blink::kWebNavigationPolicyDownload) {
    mojo::PendingRemote<blink::mojom::BlobURLToken> blob_url_token =
        CloneBlobURLToken(info->blob_url_token);

    frame_->DownloadURL(info->url_request,
                        network::mojom::RedirectMode::kFollow,
                        std::move(blob_url_token));
    return;
  }
  if (info->navigation_policy != blink::kWebNavigationPolicyCurrentTab) {
    OpenURL(std::move(info));
    return;
  }

  // Execute the BeforeUnload event. If asked not to proceed or the frame is
  // destroyed, ignore the navigation.
  // Keep a WeakPtr to this RenderFrameHost to detect if executing the
  // BeforeUnload event destroyed this frame.
  base::WeakPtr<RenderFrameImpl> weak_self = weak_factory_.GetWeakPtr();

  base::TimeTicks renderer_before_unload_start = base::TimeTicks::Now();
  if (!frame_->DispatchBeforeUnloadEvent(info->navigation_type ==
                                         blink::kWebNavigationTypeReload) ||
      !weak_self) {
    return;
  }
  base::TimeTicks renderer_before_unload_end = base::TimeTicks::Now();

  if (!info->form.IsNull()) {
    for (auto& observer : observers_)
      observer.WillSubmitForm(info->form);
  }

  if (mhtml_body_loader_client_) {
    mhtml_body_loader_client_->Detach();
    mhtml_body_loader_client_.reset();
  }

  // In certain cases, Blink re-navigates to about:blank when creating a new
  // browsing context (when opening a new window or creating an iframe) and
  // expects the navigation to complete synchronously.
  // TODO(crbug.com/40184245): Remove the synchronous about:blank
  // navigation.
  bool should_do_synchronous_about_blank_navigation =
      // Mainly a proxy for checking about:blank, even though it can match
      // other things like about:srcdoc (or any empty document schemes that
      // are registered).
      // TODO(crbug.com/40184245): Tighten the condition to only accept
      // about:blank or an empty URL which defaults to about:blank, per the
      // spec:
      // https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-iframe-element:about:blank
      WebDocumentLoader::WillLoadUrlAsEmpty(url) &&
      // The navigation method must be "GET". This is to avoid issues like
      // https://crbug.com/1210653, where a form submits to about:blank
      // targeting a new window using a POST. The browser never expects this
      // to happen synchronously because it only expects the synchronous
      // about:blank navigation to originate from browsing context creation,
      // which will always be GET requests.
      info->url_request.HttpMethod().Equals("GET") &&
      // If the frame has committed or even started a navigation before, this
      // navigation can't possibly be triggered by browsing context creation,
      // which would have triggered the navigation synchronously as the first
      // navigation in this frame. Note that we check both
      // IsOnInitialEmptyDocument() and `first_navigation_in_render_frame`
      // here because `first_navigation_in_render_frame` only tracks the state
      // in this *RenderFrame*, so it will be true even if this navigation
      // happens on a frame that has existed before in another process (e.g.
      // an <iframe> pointing to a.com being navigated to a cross-origin
      // about:blank document that happens in a new frame). Meanwhile,
      // IsOnInitialEmptyDocument() tracks the state of the frame, so it will
      // be true in the aforementioned case and we would not do a synchronous
      // commit here.
      frame_->IsOnInitialEmptyDocument() && first_navigation_in_render_frame &&
      // If this is a subframe history navigation that should be sent to the
      // browser, don't commit it synchronously.
      !is_history_navigation_in_new_child_frame &&
      // Synchronous about:blank commits on iframes should only be triggered
      // when first creating the iframe with an unset/about:blank URL, which
      // means the origin should inherit from the parent.
      (IsMainFrame() || info->url_request.RequestorOrigin().IsSameOriginWith(
                            static_cast<WebLocalFrame*>(frame_->Parent())
                                ->GetDocument()
                                .GetSecurityOrigin()));

  if (should_do_synchronous_about_blank_navigation) {
    for (auto& observer : observers_)
      observer.DidStartNavigation(url, info->navigation_type);
    SynchronouslyCommitAboutBlankForBug778318(std::move(info));
    return;
  }

  if (!frame_->WillStartNavigation(*info)) {
    return;
  }

  for (auto& observer : observers_) {
    observer.DidStartNavigation(info->url_request.Url(), info->navigation_type);
  }

  // Everything else is handled asynchronously by the browser process through
  // BeginNavigation.
  // base::Unretained() is safe to use here because if the callback
  // is retained, it's by the member of this class.
  auto do_begin_navigation = base::BindOnce(
      &RenderFrameImpl::BeginNavigationInternal, base::Unretained(this),
      std::move(info), is_history_navigation_in_new_child_frame,
      renderer_before_unload_start, renderer_before_unload_end);
  client_navigation_throttler_.DispatchOrScheduleNavigation(
      std::move(do_begin_navigation));
}

void RenderFrameImpl::SynchronouslyCommitAboutBlankForBug778318(
    std::unique_ptr<blink::WebNavigationInfo> info) {
  CHECK_EQ(NavigationCommitState::kInitialEmptyDocument,
           navigation_commit_state_);
  navigation_commit_state_ = NavigationCommitState::kNone;
  AssertNavigationCommits assert_navigation_commits(this);

  // TODO(dgozman): should we follow the RFI::CommitNavigation path instead?
  auto navigation_params = WebNavigationParams::CreateFromInfo(*info);
  // This quirk is internal to the renderer, so just reuse the previous
  // DocumentToken.
  navigation_params->document_token = frame_->GetDocument().Token();
  navigation_params->is_synchronous_commit_for_bug_778318 = true;
  // We need the provider to be non-null, otherwise Blink crashes, even
  // though the provider should not be used for any actual networking.
  navigation_params->service_worker_network_provider =
      ServiceWorkerNetworkProviderForFrame::CreateInvalidInstance();
  // The synchronous about:blank commit should only happen when the frame is
  // currently showing the initial empty document. For iframes, all navigations
  // that happen on the initial empty document should result in replacement, we
  // must have set the `frame_load_type` to kReplaceCurrentItem. For main frames
  // there are still cases where we will append instead of replace, but the
  // browser already expects this case.
  // TODO(crbug.com/40184245): Ensure main frame cases always do
  // replacement too.
  DCHECK(IsMainFrame() || navigation_params->frame_load_type ==
                              WebFrameLoadType::kReplaceCurrentItem);

  // This corresponds to steps 3 and 20 of
  // https://html.spec.whatwg.org/multipage/browsers.html#creating-a-new-browsing-context,
  // which sets the new Document's `referrer` member to the initiator frame's
  // full unredacted URL, in the case of new browsing context creation.
  //
  // The initiator might no longer exist however, in which case we cannot get
  // its document's full URL to use as the referrer.
  if (info->initiator_frame_token.has_value() &&
      WebFrame::FromFrameToken(info->initiator_frame_token.value())) {
    WebFrame* initiator =
        WebFrame::FromFrameToken(info->initiator_frame_token.value());
    DCHECK(initiator->IsWebLocalFrame());
    navigation_params->referrer =
        initiator->ToWebLocalFrame()->GetDocument().Url().GetString();
  }

  // To prevent pages from being able to abuse window.open() to determine the
  // system entropy, always set a fixed value of 'normal', for consistency with
  // other top-level navigations.
  if (IsMainFrame()) {
    navigation_params->navigation_timings.system_entropy_at_navigation_start =
        blink::mojom::SystemEntropy::kNormal;
  } else {
    // Sub frames always have an empty entropy state since they are generally
    // renderer-initiated. See
    // https://docs.google.com/document/d/1D6DqptsCEd3wPRsZ0q1iwVBAXXmhxZuLV-KKFI0ptCg/edit?usp=sharing
    // for background.
    DCHECK_EQ(blink::mojom::SystemEntropy::kEmpty,
              navigation_params->navigation_timings
                  .system_entropy_at_navigation_start);
  }

  frame_->CommitNavigation(std::move(navigation_params), BuildDocumentState());
}

// mojom::MhtmlFileWriter implementation
// ----------------------------------------

void RenderFrameImpl::SerializeAsMHTML(mojom::SerializeAsMHTMLParamsPtr params,
                                       SerializeAsMHTMLCallback callback) {
  TRACE_EVENT0("page-serialization", "RenderFrameImpl::SerializeAsMHTML");

  // Unpack payload.
  const WebString mhtml_boundary =
      WebString::FromUTF8(params->mhtml_boundary_marker);
  DCHECK(!mhtml_boundary.IsEmpty());

  // Holds WebThreadSafeData instances for some or all of header, contents and
  // footer.
  std::vector<WebThreadSafeData> mhtml_contents;
  auto delegate =
      std::make_unique<MHTMLPartsGenerationDelegateImpl>(std::move(params));

  // Generate MHTML header if needed.
  if (IsMainFrame()) {
    TRACE_EVENT0("page-serialization",
                 "RenderFrameImpl::SerializeAsMHTML header");
    // The returned data can be empty if the main frame should be skipped. If
    // the main frame is skipped, then the whole archive is bad.
    mhtml_contents.emplace_back(WebFrameSerializer::GenerateMHTMLHeader(
        mhtml_boundary, GetWebFrame(), delegate.get()));
  }

  // Generate MHTML parts.  Note that if this is not the main frame, then even
  // skipping the whole parts generation step is not an error - it simply
  // results in an omitted resource in the final file.
  TRACE_EVENT0("page-serialization",
               "RenderFrameImpl::SerializeAsMHTML parts serialization");
  MHTMLPartsGenerationDelegateImpl* delegate_ptr = delegate.get();
  WebFrameSerializer::GenerateMHTMLParts(
      mhtml_boundary, GetWebFrame(), delegate_ptr,
      base::BindOnce(&RenderFrameImpl::OnSerializeMHTMLComplete,
                     weak_factory_.GetWeakPtr(), std::move(delegate),
                     std::move(callback), std::move(mhtml_contents)));
}

void RenderFrameImpl::OnSerializeMHTMLComplete(
    std::unique_ptr<MHTMLPartsGenerationDelegateImpl> delegate,
    SerializeAsMHTMLCallback callback,
    std::vector<blink::WebThreadSafeData> mhtml_contents,
    blink::WebThreadSafeData frame_mhtml_data) {
  TRACE_EVENT0("page-serialization",
               "RenderFrameImpl::SerializeAsMHTML parts serialization");
  // The returned data can be empty if the frame should be skipped, but this
  // is OK.
  mhtml_contents.emplace_back(frame_mhtml_data);
  bool has_some_data = false;
  for (const auto& c : mhtml_contents) {
    if (!c.IsEmpty()) {
      has_some_data = true;
      break;
    }
  }

  // Note: the MHTML footer is written by the browser process, after the last
  // frame is serialized by a renderer process.

  MHTMLHandleWriterDelegate handle_delegate(
      *delegate->TakeParams(),
      base::BindOnce(&RenderFrameImpl::OnWriteMHTMLComplete,
                     weak_factory_.GetWeakPtr(), std::move(callback),
                     delegate->TakeSerializedResourcesUriDigests()),
      GetTaskRunner(blink::TaskType::kInternalDefault));

  if (has_some_data) {
    handle_delegate.WriteContents(mhtml_contents);
  } else {
    handle_delegate.Finish(mojom::MhtmlSaveStatus::kSuccess);
  }
}

void RenderFrameImpl::OnWriteMHTMLComplete(
    SerializeAsMHTMLCallback callback,
    std::unordered_set<std::string> serialized_resources_uri_digests,
    mojom::MhtmlSaveStatus save_status) {
  TRACE_EVENT1("page-serialization", "RenderFrameImpl::OnWriteMHTMLComplete",
               "frame save status", save_status);
  DCHECK(RenderThread::IsMainThread())
      << "Must run in the main renderer thread";

  // Convert the set into a vector for transport.
  std::vector<std::string> digests_of_new_parts(
      std::make_move_iterator(serialized_resources_uri_digests.begin()),
      std::make_move_iterator(serialized_resources_uri_digests.end()));

  // Notify the browser process about completion using the callback.
  std::move(callback).Run(save_status, std::move(digests_of_new_parts));
}

#ifndef STATIC_ASSERT_ENUM
#define STATIC_ASSERT_ENUM(a, b)                            \
  static_assert(static_cast<int>(a) == static_cast<int>(b), \
                "mismatching enums: " #a)
#undef STATIC_ASSERT_ENUM
#endif

void RenderFrameImpl::RequestOverlayRoutingToken(
    media::RoutingTokenCallback callback) {
  std::move(callback).Run(GetWebFrame()->GetFrameToken().value());
}

void RenderFrameImpl::OpenURL(std::unique_ptr<blink::WebNavigationInfo> info) {
  // A valid RequestorOrigin is always expected to be present.
  DCHECK(!info->url_request.RequestorOrigin().IsNull());

  WebNavigationPolicy policy = info->navigation_policy;
  auto params = blink::mojom::OpenURLParams::New();
  params->url = info->url_request.Url();
  params->initiator_origin = info->url_request.RequestorOrigin();
  if (info->requestor_base_url.IsValid()) {
    params->initiator_base_url = info->requestor_base_url;
  }
  params->actual_navigation_start = info->actual_navigation_start;
  params->post_body = blink::GetRequestBodyForWebURLRequest(info->url_request);
  DCHECK_EQ(!!params->post_body, IsHttpPost(info->url_request));
  params->extra_headers =
      blink::GetWebURLRequestHeadersAsString(info->url_request).Latin1();

  params->referrer = blink::mojom::Referrer::New(
      blink::WebStringToGURL(info->url_request.ReferrerString()),
      info->url_request.GetReferrerPolicy());
  params->disposition = NavigationPolicyToDisposition(policy);
  params->triggering_event_info = info->triggering_event_info;
  params->blob_url_token = CloneBlobURLToken(info->blob_url_token);
  params->should_replace_current_entry =
      info->frame_load_type == WebFrameLoadType::kReplaceCurrentItem &&
      GetWebView()->HistoryBackListCount() +
          GetWebView()->HistoryForwardListCount() + 1;
  params->user_gesture = info->has_transient_user_activation;
  params->is_unfenced_top_navigation = info->is_unfenced_top_navigation;
  params->initiator_navigation_state_keep_alive_handle =
      std::move(info->initiator_navigation_state_keep_alive_handle);

  params->initiator_frame_token = info->initiator_frame_token;

  // TODO(antoniosartori): Consider plumbing in the source location also for
  // navigations performed via OpenURL.
  params->source_location = network::mojom::SourceLocation::New();

  params->impression = info->impression;

  if (GetContentClient()->renderer()->AllowPopup())
    params->user_gesture = true;

  // A main frame navigation should already have consumed an activation in
  // FrameLoader::StartNavigation.
  DCHECK(!is_main_frame_ || !frame_->HasTransientUserActivation());
  if (!is_main_frame_ &&
      (policy == blink::kWebNavigationPolicyNewBackgroundTab ||
       policy == blink::kWebNavigationPolicyNewForegroundTab ||
       policy == blink::kWebNavigationPolicyNewWindow ||
       policy == blink::kWebNavigationPolicyNewPopup ||
       policy == blink::kWebNavigationPolicyPictureInPicture)) {
    frame_->ConsumeTransientUserActivation();
  }

  params->href_translate = info->href_translate.Latin1();

  bool current_frame_has_download_sandbox_flag = !frame_->IsAllowedToDownload();
  bool has_download_sandbox_flag =
      info->initiator_frame_has_download_sandbox_flag ||
      current_frame_has_download_sandbox_flag;
  bool from_ad = info->initiator_frame_is_ad || frame_->IsAdFrame();

  params->download_policy.ApplyDownloadFramePolicy(
      info->is_opener_navigation, info->url_request.HasUserGesture(),
      info->url_request.RequestorOrigin().CanAccess(
          frame_->GetSecurityOrigin()),
      has_download_sandbox_flag, from_ad);

  params->initiator_activation_and_ad_status =
      blink::GetNavigationInitiatorActivationAndAdStatus(
          info->url_request.HasUserGesture(), info->initiator_frame_is_ad,
          info->is_ad_script_in_stack);

  params->has_rel_opener = info->has_rel_opener;

  GetFrameHost()->OpenURL(std::move(params));
}

void RenderFrameImpl::SetLoaderFactoryBundle(
    scoped_refptr<blink::ChildURLLoaderFactoryBundle> loader_factories) {
  // `background_resource_fetch_context_` will be lazy initialized the first
  // time MaybeGetBackgroundResourceFetchAssets() is called if
  // BackgroundResourceFetch feature is enabled.
  background_resource_fetch_context_.reset();
  loader_factories_ = std::move(loader_factories);
}

blink::ChildURLLoaderFactoryBundle* RenderFrameImpl::GetLoaderFactoryBundle() {
  // GetLoaderFactoryBundle should not be called before `loader_factories_` have
  // been set up - before a document is committed (e.g. before a navigation
  // commits or the initial empty document commits) it is not possible to 1)
  // trigger subresource loads, or 2) trigger propagation of the factories into
  // a new frame.
  DCHECK(loader_factories_);

  return loader_factories_.get();
}

scoped_refptr<blink::ChildURLLoaderFactoryBundle>
RenderFrameImpl::CreateLoaderFactoryBundle(
    std::unique_ptr<blink::PendingURLLoaderFactoryBundle> info,
    std::optional<std::vector<blink::mojom::TransferrableURLLoaderPtr>>
        subresource_overrides,
    mojo::PendingRemote<network::mojom::URLLoaderFactory>
        subresource_proxying_loader_factory,
    mojo::PendingRemote<network::mojom::URLLoaderFactory>
        keep_alive_loader_factory,
    mojo::PendingAssociatedRemote<blink::mojom::FetchLaterLoaderFactory>
        fetch_later_loader_factory) {
  DCHECK(info);
  // We don't check `DCHECK(info->pending_default_factory())`, because it will
  // be missing for speculative frames (and in other cases where no subresource
  // loads are expected - e.g. in test frames created via RenderViewTest).  See
  // also the DCHECK in URLLoaderFactoryBundle::GetFactory.

  // If resource metadata is present, construct an in-process resource loader
  // and have it intercept requests it may be able to service.
  info = MaybeSetUpLocalResourceLoader(std::move(info));

  auto loader_factories =
      base::MakeRefCounted<blink::HostChildURLLoaderFactoryBundle>(
          GetTaskRunner(blink::TaskType::kInternalLoading));

  loader_factories->Update(
      std::make_unique<blink::ChildPendingURLLoaderFactoryBundle>(
          std::move(info)));

  if (subresource_overrides) {
    loader_factories->UpdateSubresourceOverrides(&*subresource_overrides);
  }
  if (subresource_proxying_loader_factory) {
    loader_factories->SetSubresourceProxyingLoaderFactory(
        std::move(subresource_proxying_loader_factory));
  }
  if (keep_alive_loader_factory) {
    loader_factories->SetKeepAliveLoaderFactory(
        std::move(keep_alive_loader_factory));
  }
  if (base::FeatureList::IsEnabled(blink::features::kFetchLaterAPI) &&
      fetch_later_loader_factory) {
    loader_factories->SetFetchLaterLoaderFactory(
        std::move(fetch_later_loader_factory));
  }

  return loader_factories;
}

void RenderFrameImpl::UpdateEncoding(WebFrame* frame,
                                     const std::string& encoding_name) {
  // Only update main frame's encoding_name.
  if (!frame->Parent()) {
    // TODO(crbug.com/40188381): Move `UpdateEncoding()` to the
    // `LocalMainFrameHost` interface where it makes sense. That is not a simple
    // as just migrating the method, since upon main frame creation we attempt
    // to send the encoding information before
    // `WebViewImpl::local_main_frame_host_remote_` is set-up, which breaks
    // things.`
    GetFrameHost()->UpdateEncoding(encoding_name);
  }
}

void RenderFrameImpl::SyncSelectionIfRequired(blink::SyncCondition force_sync) {
  std::u16string text;
  size_t offset;
  gfx::Range range;
  {
    WebInputMethodController* controller = frame_->GetInputMethodController();
    WebRange selection = controller->GetSelectionOffsets();
    if (selection.IsNull())
      return;

    range = gfx::Range(selection.StartOffset(), selection.EndOffset());

    if (controller->TextInputType() != blink::kWebTextInputTypeNone) {
      // If current focused element is editable, we will send 100 more chars
      // before and after selection. It is for input method surrounding text
      // feature.
      if (selection.StartOffset() > kExtraCharsBeforeAndAfterSelection)
        offset = selection.StartOffset() - kExtraCharsBeforeAndAfterSelection;
      else
        offset = 0;
      size_t length =
          selection.EndOffset() - offset + kExtraCharsBeforeAndAfterSelection;
      WebString value = controller->TextInputInfo().value;
      text = value.IsNull() ? value.Utf16()
                            : value.Substring(offset, length).Utf16();
    } else {
      offset = selection.StartOffset();
      text = frame_->SelectionAsText().Utf16();
      // http://crbug.com/101435
      // In some case, frame->selectionAsText() returned text's length is not
      // equal to the length returned from frame_->GetSelectionOffsets(). So we
      // have to set the range according to text.length().
      range.set_end(range.start() + text.length());
    }
  }

  // TODO(dglazkov): Investigate if and why this would be happening,
  // and resolve this. We shouldn't be carrying selection text here.
  // http://crbug.com/632920.
  // Sometimes we get repeated didChangeSelection calls from webkit when
  // the selection hasn't actually changed. We don't want to report these
  // because it will cause us to continually claim the X clipboard.
  if (force_sync == blink::SyncCondition::kForced ||
      selection_text_offset_ != offset || selection_range_ != range ||
      selection_text_ != text) {
    selection_text_ = text;
    selection_text_offset_ = offset;
    selection_range_ = range;
    SetSelectedText(text, offset, range);
  }
  GetLocalRootWebFrameWidget()->UpdateSelectionBounds();
}

void RenderFrameImpl::CreateAudioInputStream(
    blink::CrossVariantMojoRemote<
        blink::mojom::RendererAudioInputStreamFactoryClientInterfaceBase>
        client,
    const base::UnguessableToken& session_id,
    const media::AudioParameters& params,
    bool automatic_gain_control,
    uint32_t shared_memory_count,
    blink::CrossVariantMojoReceiver<
        media::mojom::AudioProcessorControlsInterfaceBase> controls_receiver,
    const media::AudioProcessingSettings* settings) {
  DCHECK_EQ(!!settings, !!controls_receiver);
  media::mojom::AudioProcessingConfigPtr processing_config;
  if (controls_receiver) {
    DCHECK(settings);
    processing_config = media::mojom::AudioProcessingConfig::New(
        std::move(controls_receiver), *settings);
  }

  GetAudioInputStreamFactory()->CreateStream(
      std::move(client), session_id, params, automatic_gain_control,
      shared_memory_count, std::move(processing_config));
}

void RenderFrameImpl::AssociateInputAndOutputForAec(
    const base::UnguessableToken& input_stream_id,
    const std::string& output_device_id) {
  GetAudioInputStreamFactory()->AssociateInputAndOutputForAec(input_stream_id,
                                                              output_device_id);
}

void RenderFrameImpl::InitializeMediaStreamDeviceObserver() {
  RenderThreadImpl* render_thread = RenderThreadImpl::current();
  if (!render_thread)  // Will be NULL during unit tests.
    return;

  DCHECK(!web_media_stream_device_observer_);
  web_media_stream_device_observer_ =
      std::make_unique<blink::WebMediaStreamDeviceObserver>(GetWebFrame());
}

void RenderFrameImpl::BeginNavigationInternal(
    std::unique_ptr<blink::WebNavigationInfo> info,
    bool is_history_navigation_in_new_child_frame,
    base::TimeTicks renderer_before_unload_start,
    base::TimeTicks renderer_before_unload_end) {
  // Provisional frames shouldn't initiate navigations.
  CHECK(!GetWebFrame()->IsProvisional());

  is_requesting_navigation_ = true;

  // Set SiteForCookies.
  WebDocument frame_document = frame_->GetDocument();
  if (info->frame_type == blink::mojom::RequestContextFrameType::kTopLevel) {
    info->url_request.SetSiteForCookies(
        net::SiteForCookies::FromUrl(info->url_request.Url()));
  } else {
    info->url_request.SetSiteForCookies(frame_document.SiteForCookies());
  }

  ui::PageTransition transition_type = GetTransitionType(
      ui::PAGE_TRANSITION_LINK,
      info->frame_load_type == WebFrameLoadType::kReplaceCurrentItem,
      IsMainFrame(), GetWebView()->IsFencedFrameRoot(), info->navigation_type);
  if (info->is_client_redirect) {
    transition_type = ui::PageTransitionFromInt(
        transition_type | ui::PAGE_TRANSITION_CLIENT_REDIRECT);
  }

  // Note: At this stage, the goal is to apply all the modifications the
  // renderer wants to make to the request, and then send it to the browser, so
  // that the actual network request can be started. Ideally, all such
  // modifications should take place in WillSendRequestInternal, and in the
  // implementation of willSendRequest for the various InspectorAgents
  // (devtools).
  //
  // TODO(clamy): Apply devtools override.
  // TODO(clamy): Make sure that navigation requests are not modified somewhere
  // else in blink.
  bool for_outermost_main_frame = frame_->IsOutermostMainFrame();
  {
    // upstream_url can be empty here because ForRedirect(false) implies that
    // this isn't a browser initiated navigation.
    std::optional<blink::WebURL> adjusted_request_url = WillSendRequestInternal(
        info->url_request.Url(), info->url_request.RequestorOrigin(),
        info->url_request.SiteForCookies(), ForRedirect(false),
        /*upstream_url=*/GURL(), transition_type);
    if (adjusted_request_url.has_value()) {
      info->url_request.SetUrl(adjusted_request_url.value());
    }
  }
  FinalizeRequestInternal(info->url_request, for_outermost_main_frame,
                          transition_type);
  // The extra data was created in WillSendRequestInternal if it didn't exist.
  DCHECK(info->url_request.GetURLRequestExtraData());

  // These values are assumed on the browser side for navigations. These checks
  // ensure the renderer has the correct values.
  DCHECK_EQ(network::mojom::RequestMode::kNavigate,
            info->url_request.GetMode());
  DCHECK_EQ(network::mojom::CredentialsMode::kInclude,
            info->url_request.GetCredentialsMode());
  DCHECK_EQ(network::mojom::RedirectMode::kManual,
            info->url_request.GetRedirectMode());
  DCHECK(frame_->Parent() ||
         info->frame_type == blink::mojom::RequestContextFrameType::kTopLevel);
  DCHECK(!frame_->Parent() ||
         info->frame_type == blink::mojom::RequestContextFrameType::kNested);

  bool is_form_submission =
      (info->navigation_type == blink::kWebNavigationTypeFormSubmitted ||
       info->navigation_type ==
           blink::kWebNavigationTypeFormResubmittedBackForward ||
       info->navigation_type == blink::kWebNavigationTypeFormResubmittedReload);

  bool was_initiated_by_link_click =
      info->navigation_type == blink::kWebNavigationTypeLinkClicked;

  GURL searchable_form_url;
  std::string searchable_form_encoding;
  if (!info->form.IsNull()) {
    WebSearchableFormData web_searchable_form_data(info->form);
    searchable_form_url = web_searchable_form_data.Url();
    searchable_form_encoding = web_searchable_form_data.Encoding().Utf8();
  }

  GURL client_side_redirect_url;
  if (info->is_client_redirect)
    client_side_redirect_url = frame_->GetDocument().Url();

  mojo::PendingRemote<blink::mojom::BlobURLToken> blob_url_token(
      CloneBlobURLToken(info->blob_url_token));

  int load_flags = info->url_request.GetLoadFlagsForWebUrlRequest();
  std::optional<base::Value::Dict> devtools_initiator;
  if (!info->devtools_initiator_info.IsNull()) {
    std::optional<base::Value> devtools_initiator_value =
        base::JSONReader::Read(info->devtools_initiator_info.Utf8(),
                               base::JSON_PARSE_CHROMIUM_EXTENSIONS);
    if (devtools_initiator_value && devtools_initiator_value->is_dict()) {
      devtools_initiator = std::move(*devtools_initiator_value).TakeDict();
    }
  }

  blink::mojom::NavigationInitiatorActivationAndAdStatus
      initiator_activation_and_ad_status =
          blink::GetNavigationInitiatorActivationAndAdStatus(
              info->url_request.HasUserGesture(), info->initiator_frame_is_ad,
              info->is_ad_script_in_stack);

  blink::mojom::BeginNavigationParamsPtr begin_params =
      blink::mojom::BeginNavigationParams::New(
          info->initiator_frame_token,
          blink::GetWebURLRequestHeadersAsString(info->url_request).Latin1(),
          load_flags, info->url_request.GetSkipServiceWorker(),
          blink::GetRequestContextTypeForWebURLRequest(info->url_request),
          blink::GetMixedContentContextTypeForWebURLRequest(info->url_request),
          is_form_submission, was_initiated_by_link_click,
          info->force_history_push, searchable_form_url,
          searchable_form_encoding, client_side_redirect_url,
          std::move(devtools_initiator),
          info->url_request.TrustTokenParams()
              ? info->url_request.TrustTokenParams()->Clone()
              : nullptr,
          info->impression, renderer_before_unload_start,
          renderer_before_unload_end, initiator_activation_and_ad_status,
          info->is_container_initiated, info->storage_access_api_status,
          info->has_rel_opener);

  bool current_frame_has_download_sandbox_flag = !frame_->IsAllowedToDownload();
  bool has_download_sandbox_flag =
      info->initiator_frame_has_download_sandbox_flag ||
      current_frame_has_download_sandbox_flag;
  bool from_ad = info->initiator_frame_is_ad || frame_->IsAdFrame();

  mojo::PendingRemote<blink::mojom::NavigationStateKeepAliveHandle>
      initiator_navigation_state_keep_alive_handle =
          std::move(info->initiator_navigation_state_keep_alive_handle);

  network::mojom::RequestDestination request_destination =
      blink::GetRequestDestinationForWebURLRequest(info->url_request);

  blink::mojom::CommonNavigationParamsPtr common_params =
      MakeCommonNavigationParams(frame_->GetSecurityOrigin(), std::move(info),
                                 load_flags, has_download_sandbox_flag, from_ad,
                                 is_history_navigation_in_new_child_frame,
                                 request_destination);

  bool is_duplicate_navigation = false;
  base::TimeDelta nav_start_diff;

  if (navigation_client_impl_ &&
      navigation_client_impl_->HasBeginNavigationParams()) {
    // We ignore navigations that are identical to the ongoing navigation. This
    // is because the navigation is likely to be accidental (e.g. user clicked
    // the same link multiple times, etc).
    auto& prev_begin_params = navigation_client_impl_->begin_params();
    auto& prev_common_params = navigation_client_impl_->common_params();
    if (begin_params->was_initiated_by_link_click ==
            prev_begin_params.was_initiated_by_link_click &&
        common_params->url == prev_common_params.url &&
        common_params->method == "GET" && prev_common_params.method == "GET" &&
        common_params->initiator_origin ==
            prev_common_params.initiator_origin &&
        common_params->has_user_gesture ==
            prev_common_params.has_user_gesture &&
        common_params->referrer == prev_common_params.referrer &&
        common_params->transition == prev_common_params.transition &&
        common_params->should_replace_current_entry ==
            prev_common_params.should_replace_current_entry &&
        begin_params->headers == prev_begin_params.headers &&
        begin_params->has_rel_opener == prev_begin_params.has_rel_opener) {
      is_duplicate_navigation = true;
      nav_start_diff = (common_params->navigation_start -
                        prev_common_params.navigation_start);
    }
  }
  base::UmaHistogramBoolean(
      "Navigation.RendererInitiated.IsDuplicateWithoutThresholdCheck2",
      is_duplicate_navigation);
  if (is_duplicate_navigation) {
    // The navigation is similar to a previous navigation. Check if it's started
    // close enough to the start of the previous navigation, in which case we
    // can just ignore the new navigation and keep the previous navigation.
    bool start_diff_under_threshold =
        (nav_start_diff <= features::kDuplicateNavThreshold.Get());
    base::UmaHistogramBoolean(
        "Navigation.RendererInitiated.DuplicateNavIsUnderThreshold2",
        start_diff_under_threshold);
    base::UmaHistogramTimes(
        "Navigation.RendererInitiated.DuplicateNavStartTimeDiff2",
        nav_start_diff);
    if (start_diff_under_threshold &&
        base::FeatureList::IsEnabled(features::kIgnoreDuplicateNavs)) {
      if (!base::FeatureList::IsEnabled(
              features::kIgnoreDuplicateNavsOnlyWithUserGesture) ||
          common_params->has_user_gesture) {
        DVLOG(0) << "Ignoring duplicate navigation to " << common_params->url
                 << " due to the short interval of " << nav_start_diff
                 << " since the previous one.";
        return;
      }
    }
  }

  mojo::PendingAssociatedRemote<mojom::NavigationClient>
      navigation_client_remote;
  BindNavigationClientWithParams(
      navigation_client_remote.InitWithNewEndpointAndPassReceiver(),
      begin_params.Clone(), common_params.Clone(), is_duplicate_navigation);
  mojo::PendingReceiver<mojom::NavigationRendererCancellationListener>
      renderer_cancellation_listener_receiver;
  navigation_client_impl_->SetUpRendererInitiatedNavigation(
      renderer_cancellation_listener_receiver.InitWithNewPipeAndPassRemote());

  GetFrameHost()->BeginNavigation(
      std::move(common_params), std::move(begin_params),
      std::move(blob_url_token), std::move(navigation_client_remote),
      std::move(initiator_navigation_state_keep_alive_handle),
      std::move(renderer_cancellation_listener_receiver));
}

void RenderFrameImpl::DecodeDataURL(
    const blink::mojom::CommonNavigationParams& common_params,
    const blink::mojom::CommitNavigationParams& commit_params,
    std::string* mime_type,
    std::string* charset,
    std::string* data,
    GURL* base_url) {
  // A loadData request with a specified base URL.
  GURL data_url = common_params.url;
#if BUILDFLAG(IS_ANDROID)
  if (!commit_params.data_url_as_string.empty()) {
#if DCHECK_IS_ON()
    {
      std::string mime_type_tmp, charset_tmp, data_tmp;
      DCHECK(net::DataURL::Parse(data_url, &mime_type_tmp, &charset_tmp,
                                 &data_tmp));
      DCHECK(data_tmp.empty());
    }
#endif
    // If `data_url_as_string` is set, the `url` in CommonNavigationParams will
    // only contain the data: URL header and won't contain any actual data (see
    // NavigationControllerAndroid::LoadUrl()), so we should use
    // `data_url_as_string` if possible.
    data_url = GURL(commit_params.data_url_as_string);
    if (!data_url.is_valid() || !data_url.SchemeIs(url::kDataScheme)) {
      // If the given data URL is invalid, use the data: URL header as a
      // fallback.
      data_url = common_params.url;
    }
  }
#endif
  // Parse the given data, then set the `base_url`, which is used as the
  // document URL.
  if (net::DataURL::Parse(data_url, mime_type, charset, data)) {
    // Since the base URL will also be used as the document URL, we should not
    // use an empty URL. If it's empty, use the data: URL as a fallback.
    // TODO(crbug.com/40187599): Maybe this should consider
    // `data_url_as_string` too. Otherwise, the base URL might be set to the
    // data: URL header with empty data, instead of the data: URL that contains
    // the actual data.
    *base_url = common_params.base_url_for_data_url.is_empty()
                    ? common_params.url
                    : common_params.base_url_for_data_url;
  } else {
    NOTREACHED() << "Invalid URL passed: "
                 << common_params.url.possibly_invalid_spec();
  }
}

void RenderFrameImpl::SendUpdateState() {
  // Since we are sending immediately we can cancel any pending delayed sync
  // timer.
  delayed_state_sync_timer_.Stop();
  if (GetWebFrame()->GetCurrentHistoryItem().IsNull())
    return;

  GetFrameHost()->UpdateState(GetWebFrame()->CurrentHistoryItemToPageState());
}

std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
RenderFrameImpl::MaybeSetUpLocalResourceLoader(
    std::unique_ptr<blink::PendingURLLoaderFactoryBundle> factory_bundle) {
  if (!factory_bundle->local_resource_loader_config()) {
    return factory_bundle;
  }

  // The pipe to the browser-side WebUIURLLoaderFactory could be in one of two
  // places:
  //
  // 1. factory_bundle->pending_default_factory()
  // 2. factory_bundle->scheme_specific_factories
  //
  // (This may change in the future, see https://crbug.com/40091019)
  //
  // The browser process only sends the config in the first case (see call to
  // PendingURLLoaderFactoryBundle::set_local_resource_loader_config in
  // RenderFrameHostImpl::CommitNavigation), so if we're constructing a new
  // in-process resource loader we always take that as the fallback.

  // Take the existing PendingRemote and make it the fallback for a new
  // in-process resource loader.
  local_resource_loader_.emplace(
      base::ThreadPool::CreateSequencedTaskRunner(
          {base::TaskPriority::USER_BLOCKING, base::MayBlock(),
           base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}),
      std::move(factory_bundle->local_resource_loader_config()),
      std::move(factory_bundle->pending_default_factory()));
  // Create a pipe and pass the receiving end to the new in-process loader.
  mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_remote;
  local_resource_loader_
      .AsyncCall(&content::LocalResourceURLLoaderFactory::Clone)
      .WithArgs(pending_remote.InitWithNewPipeAndPassReceiver());
  // Swap in the new PendingRemote.
  factory_bundle->pending_default_factory() = std::move(pending_remote);

  return factory_bundle;
}

blink::WebURL RenderFrameImpl::LastCommittedUrlForUKM() {
  return GetLoadingUrl();
}

// Returns the "loading URL", which might be different than the "document URL"
// used in the DocumentLoader in some cases:
// - For error pages, it will return the URL that failed to load, instead of the
// chrome-error:// URL used as the document URL in the DocumentLoader.
// - For loadDataWithBaseURL() navigations, it will return the data: URL
// used to commit, instead of the "base URL" used as the document URL in the
// DocumentLoader. See comments in  BuildDocumentStateFromParams() and
// in navigation_params.mojom's `is_load_data_with_base_url` for more details.
GURL RenderFrameImpl::GetLoadingUrl() const {
  WebDocumentLoader* document_loader = frame_->GetDocumentLoader();

  GURL overriden_url;
  if (MaybeGetOverriddenURL(document_loader, &overriden_url))
    return overriden_url;

  return document_loader->GetUrl();
}

media::MediaPermission* RenderFrameImpl::GetMediaPermission() {
  if (!media_permission_dispatcher_) {
    media_permission_dispatcher_ =
        std::make_unique<MediaPermissionDispatcher>(this);
  }
  return media_permission_dispatcher_.get();
}

void RenderFrameImpl::RegisterMojoInterfaces() {
  // TODO(dcheng): Fold this interface into mojom::Frame.
  GetAssociatedInterfaceRegistry()
      ->AddInterface<blink::mojom::AutoplayConfigurationClient>(
          base::BindRepeating(&RenderFrameImpl::BindAutoplayConfiguration,
                              weak_factory_.GetWeakPtr()));

  GetAssociatedInterfaceRegistry()->AddInterface<mojom::FrameBindingsControl>(
      base::BindRepeating(&RenderFrameImpl::BindFrameBindingsControl,
                          weak_factory_.GetWeakPtr()));

  GetAssociatedInterfaceRegistry()->AddInterface<mojom::NavigationClient>(
      base::BindRepeating(&RenderFrameImpl::BindNavigationClient,
                          weak_factory_.GetWeakPtr()));

  // TODO(dcheng): Fold this interface into mojom::Frame.
  GetAssociatedInterfaceRegistry()->AddInterface<mojom::MhtmlFileWriter>(
      base::BindRepeating(&RenderFrameImpl::BindMhtmlFileWriter,
                          base::Unretained(this)));

  GetAssociatedInterfaceRegistry()
      ->AddInterface<blink::mojom::RenderAccessibility>(base::BindRepeating(
          &RenderAccessibilityManager::BindReceiver,
          base::Unretained(render_accessibility_manager_.get())));

#if BUILDFLAG(IS_ANDROID)
  GetAssociatedInterfaceRegistry()->AddInterface<mojom::GinJavaBridge>(
      base::BindRepeating(&RenderFrameImpl::BindGinJavaBridge,
                          weak_factory_.GetWeakPtr()));
#endif
}

#if BUILDFLAG(IS_ANDROID)
void RenderFrameImpl::BindGinJavaBridge(
    mojo::PendingAssociatedReceiver<mojom::GinJavaBridge> receiver) {
  mojo::MakeSelfOwnedAssociatedReceiver(
      std::make_unique<GinJavaBridgeDispatcher>(this), std::move(receiver));
}
#endif

void RenderFrameImpl::BindMhtmlFileWriter(
    mojo::PendingAssociatedReceiver<mojom::MhtmlFileWriter> receiver) {
  mhtml_file_writer_receiver_.reset();
  mhtml_file_writer_receiver_.Bind(
      std::move(receiver), GetTaskRunner(blink::TaskType::kInternalDefault));
}

scoped_refptr<network::SharedURLLoaderFactory>
RenderFrameImpl::GetURLLoaderFactory() {
  if (!RenderThreadImpl::current()) {
    // Some tests (e.g. RenderViewTests) do not have RenderThreadImpl,
    // and must create a factory override instead.
    if (url_loader_factory_override_for_test_) {
      return url_loader_factory_override_for_test_;
    }

    // If the override does not exist, try looking in the ancestor chain since
    // we might have created child frames and asked them to create a URL loader
    // factory.
    for (auto* ancestor = GetWebFrame()->Parent(); ancestor;
         ancestor = ancestor->Parent()) {
      RenderFrameImpl* ancestor_frame = RenderFrameImpl::FromWebFrame(ancestor);
      if (ancestor_frame &&
          ancestor_frame->url_loader_factory_override_for_test_) {
        return ancestor_frame->url_loader_factory_override_for_test_;
      }
    }
    // At this point we can't create anything.
    NOTREACHED();
  }
  return GetLoaderFactoryBundle();
}

blink::URLLoaderThrottleProvider*
RenderFrameImpl::GetURLLoaderThrottleProvider() {
  RenderThreadImpl* render_thread = RenderThreadImpl::current();
  // The RenderThreadImpl may not be valid in some tests.
  return render_thread ? render_thread->url_loader_throttle_provider()
                       : nullptr;
}

scoped_refptr<blink::WebBackgroundResourceFetchAssets>
RenderFrameImpl::MaybeGetBackgroundResourceFetchAssets() {
  if (!base::FeatureList::IsEnabled(
          blink::features::kBackgroundResourceFetch)) {
    return nullptr;
  }

  if (!background_resource_fetch_context_) {
    if (!background_resource_fetch_task_runner_) {
      background_resource_fetch_task_runner_ =
          base::ThreadPool::CreateSequencedTaskRunner(
              {base::TaskPriority::USER_BLOCKING});
    }
    background_resource_fetch_context_ =
        base::MakeRefCounted<BackgroundResourceFetchAssets>(
            GetLoaderFactoryBundle()->Clone(),
            GetURLLoaderThrottleProvider()
                ? GetURLLoaderThrottleProvider()->Clone()
                : nullptr,
            background_resource_fetch_task_runner_,
            frame_->GetLocalFrameToken());
  }
  return background_resource_fetch_context_;
}

void RenderFrameImpl::OnStopLoading() {
  for (auto& observer : observers_)
    observer.OnStop();
}

bool RenderFrameImpl::IsRequestingNavigation() {
  return is_requesting_navigation_;
}

void RenderFrameImpl::LoadHTMLStringForTesting(std::string_view html,
                                               const GURL& base_url,
                                               const std::string& text_encoding,
                                               const GURL& unreachable_url,
                                               bool replace_current_item) {
  AssertNavigationCommits assert_navigation_commits(
      this, kMayReplaceInitialEmptyDocument);

  mojo::PendingRemote<network::mojom::URLLoaderFactory>
      url_loader_factory_remote;
  if (url_loader_factory_override_for_test_) {
    url_loader_factory_override_for_test_->Clone(
        url_loader_factory_remote.InitWithNewPipeAndPassReceiver());
  } else {
    url_loader_factory_remote =
        network::NotImplementedURLLoaderFactory::Create();
  }

  pending_loader_factories_ = CreateLoaderFactoryBundle(
      blink::ChildPendingURLLoaderFactoryBundle::CreateFromDefaultFactoryImpl(
          std::move(url_loader_factory_remote)),
      /*subresource_overrides=*/std::nullopt,
      /*subresource_proxying_loader_factory=*/{},
      /*keep_alive_loader_factory=*/{},
      /*fetch_later_loader_factory=*/{});

  auto navigation_params = std::make_unique<WebNavigationParams>();
  navigation_params->url = base_url;
  WebNavigationParams::FillStaticResponse(navigation_params.get(), "text/html",
                                          WebString::FromUTF8(text_encoding),
                                          html);
  navigation_params->unreachable_url = unreachable_url;
  navigation_params->frame_load_type =
      replace_current_item ? blink::WebFrameLoadType::kReplaceCurrentItem
                           : blink::WebFrameLoadType::kStandard;
  navigation_params->service_worker_network_provider =
      ServiceWorkerNetworkProviderForFrame::CreateInvalidInstance();
  frame_->CommitNavigation(std::move(navigation_params), BuildDocumentState());
}

scoped_refptr<base::SingleThreadTaskRunner> RenderFrameImpl::GetTaskRunner(
    blink::TaskType task_type) {
  return GetWebFrame()->GetTaskRunner(task_type);
}

BindingsPolicySet RenderFrameImpl::GetEnabledBindings() {
  return enabled_bindings_;
}

void RenderFrameImpl::SetAccessibilityModeForTest(ui::AXMode new_mode) {
  render_accessibility_manager_->SetMode(new_mode, 1);
}

const RenderFrameMediaPlaybackOptions&
RenderFrameImpl::GetRenderFrameMediaPlaybackOptions() {
  return renderer_media_playback_options_;
}

void RenderFrameImpl::SetRenderFrameMediaPlaybackOptions(
    const RenderFrameMediaPlaybackOptions& opts) {
  renderer_media_playback_options_ = opts;
}

void RenderFrameImpl::SetAllowsCrossBrowsingInstanceFrameLookup() {
  GetWebFrame()->SetAllowsCrossBrowsingInstanceFrameLookup();
}

bool RenderFrameImpl::IsAccessibilityEnabled() const {
  return render_accessibility_manager_->GetAccessibilityMode().has_mode(
      ui::AXMode::kWebContents);
}

std::unique_ptr<blink::WebSocketHandshakeThrottle>
RenderFrameImpl::CreateWebSocketHandshakeThrottle() {
  // Lazily create the provider.
  if (!websocket_handshake_throttle_provider_) {
    websocket_handshake_throttle_provider_ =
        GetContentClient()
            ->renderer()
            ->CreateWebSocketHandshakeThrottleProvider();
    if (!websocket_handshake_throttle_provider_)
      return nullptr;
  }

  return websocket_handshake_throttle_provider_->CreateThrottle(
      frame_->GetLocalFrameToken(),
      GetTaskRunner(blink::TaskType::kInternalDefault));
}

void RenderFrameImpl::AddMessageToConsoleImpl(
    blink::mojom::ConsoleMessageLevel level,
    const std::string& message,
    bool discard_duplicates) {
  blink::WebConsoleMessage wcm(level, WebString::FromUTF8(message));
  frame_->AddMessageToConsole(wcm, discard_duplicates);
}

void RenderFrameImpl::SetURLLoaderFactoryOverrideForTest(
    scoped_refptr<network::SharedURLLoaderFactory> factory) {
  url_loader_factory_override_for_test_ = std::move(factory);
}

scoped_refptr<blink::ChildURLLoaderFactoryBundle>
RenderFrameImpl::CloneLoaderFactories() {
  auto pending_bundle = base::WrapUnique(
      static_cast<blink::TrackedChildPendingURLLoaderFactoryBundle*>(
          GetLoaderFactoryBundle()->Clone().release()));
  return base::MakeRefCounted<blink::TrackedChildURLLoaderFactoryBundle>(
      std::move(pending_bundle));
}

blink::scheduler::WebAgentGroupScheduler&
RenderFrameImpl::GetAgentGroupScheduler() {
  return agent_scheduling_group_->agent_group_scheduler();
}

url::Origin RenderFrameImpl::GetSecurityOriginOfTopFrame() {
  return frame_->Top()->GetSecurityOrigin();
}

base::WeakPtr<media::DecoderFactory> RenderFrameImpl::GetMediaDecoderFactory() {
  return media_factory_.GetDecoderFactory();
}

gfx::Rect RenderFrameImpl::ConvertViewportToWindow(const gfx::Rect& rect) {
  return GetLocalRootWebFrameWidget()->BlinkSpaceToEnclosedDIPs(rect);
}

float RenderFrameImpl::GetDeviceScaleFactor() {
  return GetLocalRootWebFrameWidget()->GetScreenInfo().device_scale_factor;
}

bool RenderFrameImpl::DeferMediaLoad(bool has_played_media_before,
                                     base::OnceClosure closure) {
  if (frame_->GetDocument().IsPrerendering()) {
    frame_->GetDocument().AddPostPrerenderingActivationStep(
        base::BindOnce(CallClientDeferMediaLoad, weak_factory_.GetWeakPtr(),
                       has_played_media_before, std::move(closure)));
    return true;
  }

  return GetContentClient()->renderer()->DeferMediaLoad(
      this, has_played_media_before, std::move(closure));
}

WebView* RenderFrameImpl::CreateNewWindow(
    const WebURLRequest& request,
    const blink::WebWindowFeatures& features,
    const WebString& frame_name,
    const gfx::Rect& requested_screen_rect,
    WebNavigationPolicy policy,
    network::mojom::WebSandboxFlags sandbox_flags,
    const blink::SessionStorageNamespaceId& session_storage_namespace_id,
    bool& consumed_user_gesture,
    const std::optional<blink::Impression>& impression,
    const std::optional<blink::WebPictureInPictureWindowOptions>& pip_options,
    const blink::WebURL& base_url) {
  consumed_user_gesture = false;
  mojom::CreateNewWindowParamsPtr params = mojom::CreateNewWindowParams::New();

  // The user activation check is done at the browser process through
  // |frame_host->CreateNewWindow()| call below.  But the extensions case
  // handled through the following |if| is an exception.
  params->allow_popup = false;
  if (GetContentClient()->renderer()->AllowPopup())
    params->allow_popup = true;

  params->window_container_type = WindowFeaturesToContainerType(features);

  params->session_storage_namespace_id = session_storage_namespace_id;
  if (!features.noopener) {
    params->clone_from_session_storage_namespace_id =
        GetWebView()->GetSessionStorageNamespaceId();
  }

  const std::string& frame_name_utf8 = frame_name.Utf8(
      WebString::UTF8ConversionMode::kStrictReplacingErrorsWithFFFD);
  params->frame_name = frame_name_utf8;
  params->opener_suppressed = features.noopener;
  params->disposition = NavigationPolicyToDisposition(policy);
  if (!request.IsNull()) {
    params->target_url = request.Url();
    // The browser process does not consider empty URLs as valid (partly due to
    // a risk of treating them as a navigation to the privileged NTP in some
    // cases), so treat an attempt to create a window with an empty URL as
    // opening about:blank.
    //
    // Similarly, javascript: URLs should not be sent to the browser process,
    // since they are either handled within the renderer process (if a window is
    // created within the same browsing context group) or ignored (in the
    // noopener case). Use about:blank for the URL in that case as well, to
    // reduce the risk of running them incorrectly.
    if (params->target_url.is_empty() ||
        params->target_url.SchemeIs(url::kJavaScriptScheme)) {
      params->target_url = GURL(url::kAboutBlankURL);
    }

    params->referrer = blink::mojom::Referrer::New(
        blink::WebStringToGURL(request.ReferrerString()),
        request.GetReferrerPolicy());
  }
  params->features = ConvertWebWindowFeaturesToMojoWindowFeatures(features);

  params->is_form_submission = request.IsFormSubmission();
  params->consumes_user_activation =
      GetWebFrame()->HasTransientUserActivation();
  params->form_submission_post_data =
      blink::GetRequestBodyForWebURLRequest(request);
  params->form_submission_post_content_type = request.HttpContentType().Utf8();

  params->impression = impression;

  if (pip_options) {
    CHECK_EQ(policy, blink::kWebNavigationPolicyPictureInPicture);
    auto pip_mojom_opts = blink::mojom::PictureInPictureWindowOptions::New();
    pip_mojom_opts->width = pip_options->width;
    pip_mojom_opts->height = pip_options->height;
    pip_mojom_opts->disallow_return_to_opener =
        pip_options->disallow_return_to_opener;
    pip_mojom_opts->prefer_initial_window_placement =
        pip_options->prefer_initial_window_placement;
    params->pip_options = std::move(pip_mojom_opts);
  }

  params->download_policy.ApplyDownloadFramePolicy(
      /*is_opener_navigation=*/false, request.HasUserGesture(),
      // `openee_can_access_opener_origin` only matters for opener navigations,
      // so its value here is irrelevant.
      /*openee_can_access_opener_origin=*/true,
      !GetWebFrame()->IsAllowedToDownload(), GetWebFrame()->IsAdFrame());

  params->initiator_activation_and_ad_status =
      blink::GetNavigationInitiatorActivationAndAdStatus(
          request.HasUserGesture(), GetWebFrame()->IsAdFrame(),
          GetWebFrame()->IsAdScriptInStack());

  // We preserve this information before sending the message since |params| is
  // moved on send.
  bool is_background_tab =
      params->disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB;

  mojo::PendingAssociatedReceiver<mojom::Frame> pending_frame_receiver;
  params->frame_remote =
      pending_frame_receiver.InitWithNewEndpointAndPassRemote();

  mojo::PendingAssociatedReceiver<blink::mojom::PageBroadcast>
      page_broadcast_receiver;
  params->page_broadcast_remote =
      page_broadcast_receiver.InitWithNewEndpointAndPassRemote();

  mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
      browser_interface_broker;
  params->main_frame_interface_broker =
      browser_interface_broker.InitWithNewPipeAndPassReceiver();

  mojo::PendingAssociatedRemote<blink::mojom::AssociatedInterfaceProvider>
      associated_interface_provider;
  params->associated_interface_provider =
      associated_interface_provider.InitWithNewEndpointAndPassReceiver();

  mojo::PendingAssociatedRemote<blink::mojom::WidgetHost> widget_host;
  params->widget_host = widget_host.InitWithNewEndpointAndPassReceiver();
  mojo::PendingAssociatedReceiver<blink::mojom::Widget> widget;
  params->widget = widget.InitWithNewEndpointAndPassRemote();
  mojo::PendingAssociatedRemote<blink::mojom::FrameWidgetHost>
      frame_widget_host;
  params->frame_widget_host =
      frame_widget_host.InitWithNewEndpointAndPassReceiver();
  mojo::PendingAssociatedReceiver<blink::mojom::FrameWidget> frame_widget;
  params->frame_widget = frame_widget.InitWithNewEndpointAndPassRemote();

  mojom::CreateNewWindowStatus status;
  mojom::CreateNewWindowReplyPtr reply;
  auto* frame_host = GetFrameHost();
  if (!frame_host->CreateNewWindow(std::move(params), &status, &reply)) {
    // The sync IPC failed, e.g. maybe the render process is in the middle of
    // shutting down. Can't create a new window without the browser process,
    // so just bail out.
    return nullptr;
  }

  // If creation of the window was blocked (e.g. because this frame doesn't
  // have user activation), return before consuming user activation. A frame
  // that isn't allowed to open a window  shouldn't be able to consume the
  // activation for the rest of the frame tree.
  if (status == mojom::CreateNewWindowStatus::kBlocked)
    return nullptr;

  // For Android WebView, we support a pop-up like behavior for window.open()
  // even if the embedding app doesn't support multiple windows. In this case,
  // window.open() will return "window" and navigate it to whatever URL was
  // passed. We also don't need to consume user gestures to protect against
  // multiple windows being opened, because, well, the app doesn't support
  // multiple windows.
  // TODO(dcheng): It's awkward that this is plumbed into Blink but not really
  // used much in Blink, except to enable web testing... perhaps this should
  // be checked directly in the browser side.
  if (status == mojom::CreateNewWindowStatus::kReuse) {
    // In this case, treat javascript: URLs as blocked rather than running them
    // in a reused main frame in Android WebView. See https://crbug.com/1083819.
    if (!request.IsNull() && request.Url().ProtocolIs(url::kJavaScriptScheme)) {
      return nullptr;
    }
    return GetWebView();
  }

  // Consume the transient user activation in the current renderer.
  consumed_user_gesture = GetWebFrame()->ConsumeTransientUserActivation(
      blink::UserActivationUpdateSource::kBrowser);

  // If we should ignore the new window (e.g. because of `noopener`), return
  // now that user activation was consumed.
  if (status == mojom::CreateNewWindowStatus::kIgnore)
    return nullptr;

  DCHECK(reply);
  DCHECK_NE(IPC::mojom::kRoutingIdNone, reply->main_frame_route_id);
  DCHECK_NE(IPC::mojom::kRoutingIdNone, reply->widget_routing_id);

  // While this view may be a background extension page, it can spawn a visible
  // render view. So we just assume that the new one is not another background
  // page instead of passing on our own value.
  // TODO(vangelis): Can we tell if the new view will be a background page?
  bool never_composited = false;

  // The initial hidden state for the RenderViewImpl here has to match what the
  // browser will eventually decide for the given disposition. Since we have to
  // return from this call synchronously, we just have to make our best guess
  // and rely on the browser sending a WasHidden / WasShown message if it
  // disagrees.
  mojom::CreateViewParamsPtr view_params = mojom::CreateViewParams::New();

  view_params->opener_frame_token = GetWebFrame()->GetFrameToken();
  view_params->window_was_opened_by_another_window = true;
  view_params->renderer_preferences = GetWebView()->GetRendererPreferences();
  view_params->web_preferences = GetWebView()->GetWebPreferences();

  view_params->replication_state = blink::mojom::FrameReplicationState::New();
  view_params->replication_state->frame_policy.sandbox_flags = sandbox_flags;
  view_params->replication_state->name = frame_name_utf8;
  view_params->devtools_main_frame_token = reply->devtools_main_frame_token;
  view_params->browsing_context_group_token =
      reply->browsing_context_group_token;
  view_params->color_provider_colors = reply->color_provider_colors;

  auto widget_params = mojom::CreateFrameWidgetParams::New();
  widget_params->routing_id = reply->widget_routing_id;
  widget_params->visual_properties = reply->visual_properties;
  widget_params->reuse_compositor = false;
  widget_params->widget_host = std::move(widget_host);
  widget_params->widget = std::move(widget);
  widget_params->frame_widget_host = std::move(frame_widget_host);
  widget_params->frame_widget = std::move(frame_widget);

  auto main_frame_params = mojom::CreateLocalMainFrameParams::New();
  main_frame_params->frame_token = reply->main_frame_token;
  main_frame_params->routing_id = reply->main_frame_route_id;
  main_frame_params->frame = std::move(pending_frame_receiver);
  main_frame_params->interface_broker = std::move(browser_interface_broker);
  main_frame_params->document_token = reply->document_token;
  main_frame_params->policy_container = std::move(reply->policy_container);
  main_frame_params->associated_interface_provider_remote =
      std::move(associated_interface_provider);
  main_frame_params->widget_params = std::move(widget_params);
  main_frame_params->subresource_loader_factories =
      base::WrapUnique(static_cast<blink::PendingURLLoaderFactoryBundle*>(
          CloneLoaderFactories()->Clone().release()));

  view_params->main_frame =
      mojom::CreateMainFrameUnion::NewLocalParams(std::move(main_frame_params));
  view_params->blink_page_broadcast = std::move(page_broadcast_receiver);
  view_params->session_storage_namespace_id =
      reply->cloned_session_storage_namespace_id;
  DCHECK(!view_params->session_storage_namespace_id.empty())
      << "Session storage namespace must be populated.";
  view_params->hidden = is_background_tab;
  view_params->never_composited = never_composited;
  view_params->partitioned_popin_params =
      std::move(reply->partitioned_popin_params);

  WebView* web_view = agent_scheduling_group_->CreateWebView(
      std::move(view_params),
      /*was_created_by_renderer=*/true, base_url);

  if (reply->widget_screen_rect.has_value() &&
      reply->window_screen_rect.has_value()) {
    CHECK(base::FeatureList::IsEnabled(blink::features::kCombineNewWindowIPCs));
    web_view->MainFrameWidget()->SetScreenRects(*reply->widget_screen_rect,
                                                *reply->window_screen_rect);
  } else {
    // Window geometry is not immediately available, use the requested bounds
    // until UpdateScreenRects() is sent from the browser.
    web_view->MainFrameWidget()->SetScreenRects(requested_screen_rect,
                                                requested_screen_rect);
  }
  web_view->MainFrameWidget()->ApplyVisualProperties(reply->visual_properties);

  if (reply->wait_for_debugger) {
    web_view->MainFrame()
        ->ToWebLocalFrame()
        ->LocalRoot()
        ->FrameWidget()
        ->WaitForDebuggerWhenShown();
  }

  return web_view;
}

std::unique_ptr<blink::WebLinkPreviewTriggerer>
RenderFrameImpl::CreateLinkPreviewTriggerer() {
  return GetContentClient()->renderer()->CreateLinkPreviewTriggerer();
}

base::ScopedClosureRunner
RenderFrameImpl::CreateScopedClientNavigationThrottler() {
  return client_navigation_throttler_.DeferNavigations();
}

void RenderFrameImpl::ResetMembersUsedForDurationOfCommit() {
  pending_loader_factories_ = nullptr;
  pending_code_cache_host_.reset();
  pending_cookie_manager_info_.reset();
  pending_storage_info_.reset();
  is_requesting_navigation_ = false;
}

}  // namespace content
