// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/web_contents/web_contents_impl.h"

#include <stddef.h>

#include <algorithm>
#include <cmath>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <string_view>
#include <tuple>
#include <utility>
#include <vector>

#include "base/auto_reset.h"
#include "base/base_switches.h"
#include "base/check_op.h"
#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/containers/flat_set.h"
#include "base/debug/crash_logging.h"
#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/user_metrics.h"
#include "base/no_destructor.h"
#include "base/observer_list.h"
#include "base/process/process.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/to_string.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/time.h"
#include "base/timer/elapsed_timer.h"
#include "base/trace_event/optional_trace_event.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "cc/input/browser_controls_offset_tag_modifications.h"
#include "components/attribution_reporting/features.h"
#include "components/download/public/common/download_stats.h"
#include "components/input/cursor_manager.h"
#include "components/input/features.h"
#include "components/input/render_widget_host_input_event_router.h"
#include "components/input/switches.h"
#include "components/input/utils.h"
#include "components/url_formatter/url_formatter.h"
#include "components/viz/common/features.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "content/browser/attribution_reporting/attribution_host.h"
#include "content/browser/attribution_reporting/attribution_manager.h"
#include "content/browser/attribution_reporting/attribution_os_level_manager.h"
#include "content/browser/bad_message.h"
#include "content/browser/browser_context_impl.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/browser_plugin/browser_plugin_embedder.h"
#include "content/browser/browser_plugin/browser_plugin_guest.h"
#include "content/browser/btm/btm_bounce_detector.h"
#include "content/browser/btm/btm_navigation_flow_detector.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/closewatcher/close_listener_manager.h"
#include "content/browser/compositor/surface_utils.h"
#include "content/browser/device_posture/device_posture_provider_impl.h"
#include "content/browser/devtools/protocol/page_handler.h"
#include "content/browser/devtools/render_frame_devtools_agent_host.h"
#include "content/browser/display_cutout/display_cutout_host_impl.h"
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
#include "content/browser/dom_storage/session_storage_namespace_impl.h"
#include "content/browser/download/mhtml_generation_manager.h"
#include "content/browser/download/save_package.h"
#include "content/browser/fenced_frame/fenced_frame.h"
#include "content/browser/find_request_manager.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/guest_page_holder_impl.h"
#include "content/browser/host_zoom_map_impl.h"
#include "content/browser/media/audio_stream_monitor.h"
#include "content/browser/media/media_web_contents_observer.h"
#include "content/browser/permissions/permission_controller_impl.h"
#include "content/browser/permissions/permission_util.h"
#include "content/browser/preloading/prefetch/prefetch_request.h"
#include "content/browser/preloading/prefetch/prefetch_service.h"
#include "content/browser/preloading/prefetch/prefetch_type.h"
#include "content/browser/preloading/preloading.h"
#include "content/browser/preloading/prerender/prerender_final_status.h"
#include "content/browser/preloading/prerender/prerender_handle_impl.h"
#include "content/browser/preloading/prerender/prerender_host_registry.h"
#include "content/browser/preloading/prerender/prerender_metrics.h"
#include "content/browser/preloading/prerender/prerender_new_tab_handle.h"
#include "content/browser/renderer_host/agent_scheduling_group_host.h"
#include "content/browser/renderer_host/cross_process_frame_connector.h"
#include "content/browser/renderer_host/frame_token_message_queue.h"
#include "content/browser/renderer_host/frame_tree_node.h"
#include "content/browser/renderer_host/input/touch_emulator_impl.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/navigation_entry_impl.h"
#include "content/browser/renderer_host/navigation_request.h"
#include "content/browser/renderer_host/page_impl.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/render_frame_proxy_host.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_delegate_view.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_factory.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
#include "content/browser/renderer_host/spare_render_process_host_manager_impl.h"
#include "content/browser/renderer_host/text_input_manager.h"
#include "content/browser/renderer_host/visible_time_request_trigger.h"
#include "content/browser/screen_details/screen_change_monitor.h"
#include "content/browser/screen_orientation/screen_orientation_provider.h"
#include "content/browser/shared_storage/shared_storage_budget_charger.h"
#include "content/browser/site_instance_impl.h"
#include "content/browser/tpcd_heuristics/opener_heuristic_tab_helper.h"
#include "content/browser/tpcd_heuristics/redirect_heuristic_tab_helper.h"
#include "content/browser/wake_lock/wake_lock_context_host.h"
#include "content/browser/web_contents/file_chooser_impl.h"
#include "content/browser/web_contents/java_script_dialog_commit_deferring_condition.h"
#include "content/browser/web_contents/partitioned_popins_controller.h"
#include "content/browser/web_contents/slow_web_preference_cache.h"
#include "content/browser/web_contents/web_contents_view.h"
#include "content/browser/web_contents/web_contents_view_child_frame.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
#include "content/browser/webui/web_ui_impl.h"
#include "content/common/content_switches_internal.h"
#include "content/common/features.h"
#include "content/public/browser/ax_inspect_factory.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_plugin_guest_manager.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/color_chooser.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/context_menu_params.h"
#include "content/public/browser/device_service.h"
#include "content/public/browser/disallow_activation_reason.h"
#include "content/public/browser/download_manager.h"
#include "content/public/browser/file_select_listener.h"
#include "content/public/browser/focused_node_details.h"
#include "content/public/browser/frame_type.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/invalidate_type.h"
#include "content/public/browser/javascript_dialog_manager.h"
#include "content/public/browser/keyboard_event_processing_result.h"
#include "content/public/browser/navigation_details.h"
#include "content/public/browser/navigation_throttle_registry.h"
#include "content/public/browser/permission_descriptor_util.h"
#include "content/public/browser/preload_pipeline_info.h"
#include "content/public/browser/preview_cancel_reason.h"
#include "content/public/browser/render_widget_host_iterator.h"
#include "content/public/browser/render_widget_host_observer.h"
#include "content/public/browser/restore_type.h"
#include "content/public/browser/scoped_accessibility_mode.h"
#include "content/public/browser/site_isolation_policy.h"
#include "content/public/browser/ssl_status.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_view_delegate.h"
#include "content/public/browser/web_ui_controller.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/referrer_type_converters.h"
#include "content/public/common/url_constants.h"
#include "ipc/constants.mojom.h"
#include "media/base/media_switches.h"
#include "net/base/url_util.h"
#include "net/http/http_util.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "partition_alloc/buildflags.h"
#include "services/device/public/mojom/wake_lock.mojom.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/request_destination.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/web_sandbox_flags.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "third_party/abseil-cpp/absl/cleanup/cleanup.h"
#include "third_party/blink/public/common/custom_handlers/protocol_handler_utils.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/loader/resource_type_util.h"
#include "third_party/blink/public/common/mime_util/mime_util.h"
#include "third_party/blink/public/common/page/page_zoom.h"
#include "third_party/blink/public/common/page_state/page_state.h"
#include "third_party/blink/public/common/permissions/permission_utils.h"
#include "third_party/blink/public/common/security/protocol_handler_security_level.h"
#include "third_party/blink/public/common/switches.h"
#include "third_party/blink/public/common/web_preferences/web_preferences.h"
#include "third_party/blink/public/common/widget/constants.h"
#include "third_party/blink/public/mojom/frame/deferred_fetch_policy.mojom-shared.h"
#include "third_party/blink/public/mojom/frame/frame.mojom.h"
#include "third_party/blink/public/mojom/frame/fullscreen.mojom.h"
#include "third_party/blink/public/mojom/image_downloader/image_downloader.mojom.h"
#include "third_party/blink/public/mojom/input/input_handler.mojom-shared.h"
#include "third_party/blink/public/mojom/mediastream/media_stream.mojom-shared.h"
#include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h"
#include "third_party/blink/public/mojom/page/draggable_region.mojom.h"
#include "third_party/blink/public/mojom/window_features/window_features.mojom.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/accessibility/ax_tree_combiner.h"
#include "ui/accessibility/platform/browser_accessibility.h"
#include "ui/accessibility/platform/browser_accessibility_manager.h"
#include "ui/base/clipboard/clipboard_metadata.h"
#include "ui/base/ime/mojom/virtual_keyboard_types.mojom.h"
#include "ui/base/mojom/window_show_state.mojom.h"
#include "ui/base/pointer/pointer_device.h"
#include "ui/base/ui_base_types.h"
#include "ui/base/window_open_disposition.h"
#include "ui/color/color_provider_key.h"
#include "ui/color/color_provider_manager.h"
#include "ui/color/color_provider_utils.h"
#include "ui/compositor/compositor.h"
#include "ui/display/screen.h"
#include "ui/display/types/display_constants.h"
#include "ui/events/base_event_utils.h"
#include "ui/gfx/animation/animation.h"

#if BUILDFLAG(IS_WIN)
#include "base/threading/thread_restrictions.h"
#include "components/stylus_handwriting/win/features.h"
#include "content/browser/renderer_host/dip_util.h"
#include "ui/gfx/geometry/dip_util.h"
#endif  // BUILDFLAG(IS_WIN)

#if BUILDFLAG(IS_ANDROID)
#include "base/android/device_info.h"
#include "base/check.h"
#include "content/browser/android/java_interfaces_impl.h"
#include "content/browser/android/nfc_host.h"
#include "content/browser/android/selection/selection_popup_controller.h"
#include "content/browser/navigation_transitions/back_forward_transition_animation_manager_android.h"
#include "content/browser/web_contents/web_contents_android.h"
#include "content/browser/web_contents/web_contents_view_android.h"
#include "content/public/browser/android/child_process_importance.h"
#include "content/public/browser/android/selection_popup_delegate.h"
#include "services/device/public/mojom/nfc.mojom.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "ui/android/event_forwarder.h"
#include "ui/android/view_android.h"
#include "ui/base/device_form_factor.h"
#else  // !BUILDFLAG(IS_ANDROID)
#include "ui/accessibility/accessibility_features.h"
#endif  // BUILDFLAG(IS_ANDROID)

#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
#include "content/browser/date_time_chooser/date_time_chooser.h"
#endif

#if BUILDFLAG(ENABLE_VR)
#include "content/browser/xr/service/xr_runtime_manager_impl.h"
#endif

#if defined(USE_AURA)
#include "ui/aura/window.h"
#include "ui/wm/core/window_util.h"
#endif

#if !BUILDFLAG(IS_ANDROID)
#include "content/public/browser/document_picture_in_picture_window_controller.h"
#include "content/public/browser/picture_in_picture_window_controller.h"
#endif  // !BUILDFLAG(IS_ANDROID)

#if BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_IOS_TVOS)
#include "content/browser/ios/nfc_host.h"
#endif

namespace content {

namespace {

// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
//
// LINT.IfChange(CrashRepHandlingOutcome)
enum class CrashRepHandlingOutcome {
  // Dialog wasn't suppressed and the crash report will be potentially queued.
  kPotentiallyQueued = 0,
  // Dialog was suppressed so the crash report was dropped.
  kDropped = 1,
  kMaxValue = kDropped,
};
// LINT.ThenChange(//tools/metrics/histograms/enums.xml:CrashRepHandlingOutcome)

// The window which we dobounce load info updates in.
constexpr auto kUpdateLoadStatesInterval = base::Milliseconds(250);

// Kill switch for inner WebContents visibility updates.
BASE_FEATURE(kUpdateInnerWebContentsVisibility,
             base::FEATURE_ENABLED_BY_DEFAULT);

using LifecycleState = RenderFrameHost::LifecycleState;
using LifecycleStateImpl = RenderFrameHostImpl::LifecycleStateImpl;
using AttributionReportingOsRegistrar =
    ContentBrowserClient::AttributionReportingOsRegistrar;

base::LazyInstance<base::RepeatingCallbackList<void(WebContents*)>>::
    DestructorAtExit g_created_callbacks = LAZY_INSTANCE_INITIALIZER;

bool HasMatchingWidgetHost(FrameTree* tree, RenderWidgetHostImpl* host) {
  // This method scans the frame tree rather than checking whether
  // host->delegate() == this, which allows it to return false when the host
  // for a frame that is pending or pending deletion.
  if (!host) {
    return false;
  }

  for (FrameTreeNode* node : tree->NodesIncludingInnerTreeNodes()) {
    // We might cross a WebContents boundary here, but it's fine as we are only
    // comparing the RWHI with the given `host`, which is always guaranteed to
    // belong to the same WebContents as `tree`.
    if (node->current_frame_host()->GetRenderWidgetHost() == host) {
      DCHECK_EQ(WebContentsImpl::FromFrameTreeNode(node),
                WebContentsImpl::FromRenderWidgetHostImpl(host));
      return true;
    }
  }
  return false;
}

RenderFrameHostImpl* FindOpenerRFH(const WebContents::CreateParams& params) {
  RenderFrameHostImpl* opener_rfh = nullptr;
  if (params.opener_render_frame_id != IPC::mojom::kRoutingIdNone) {
    opener_rfh = RenderFrameHostImpl::FromID(params.opener_render_process_id,
                                             params.opener_render_frame_id);
  }
  return opener_rfh;
}

// Returns |true| if |type| is the kind of user input that should trigger the
// user interaction observers.
bool IsUserInteractionInputType(blink::WebInputEvent::Type type) {
  // TODO(mustaq): This list should be based off the HTML spec:
  // https://html.spec.whatwg.org/multipage/interaction.html#tracking-user-activation,
  // and kGestureScrollBegin is a clear outlier.
  return type == blink::WebInputEvent::Type::kMouseDown ||
         type == blink::WebInputEvent::Type::kGestureScrollBegin ||
         type == blink::WebInputEvent::Type::kTouchStart ||
         type == blink::WebInputEvent::Type::kRawKeyDown ||
         type == blink::WebInputEvent::Type::kKeyDown;
}

// Ensures that OnDialogClosed is only called once.
class CloseDialogCallbackWrapper
    : public base::RefCountedThreadSafe<CloseDialogCallbackWrapper> {
 public:
  using CloseCallback =
      base::OnceCallback<void(bool, bool, const std::u16string&)>;

  explicit CloseDialogCallbackWrapper(CloseCallback callback)
      : callback_(std::move(callback)) {}

  void Run(bool dialog_was_suppressed,
           bool success,
           const std::u16string& user_input) {
    if (callback_.is_null()) {
      return;
    }
    std::move(callback_).Run(dialog_was_suppressed, success, user_input);
  }

 private:
  friend class base::RefCountedThreadSafe<CloseDialogCallbackWrapper>;
  ~CloseDialogCallbackWrapper() = default;

  CloseCallback callback_;
};

bool FrameCompareDepth(RenderFrameHostImpl* a, RenderFrameHostImpl* b) {
  return a->GetFrameDepth() < b->GetFrameDepth();
}

bool AreValidRegisterProtocolHandlerArguments(
    const std::string& protocol,
    const GURL& url,
    const url::Origin& origin,
    blink::ProtocolHandlerSecurityLevel security_level) {
  ChildProcessSecurityPolicyImpl* policy =
      ChildProcessSecurityPolicyImpl::GetInstance();
  if (policy->IsPseudoScheme(protocol)) {
    return false;
  }

  // Implementation of the protocol handler arguments normalization steps
  // defined in the spec.
  // https://html.spec.whatwg.org/multipage/system-state.html#normalize-protocol-handler-parameters
  //
  // Verify custom handler schemes for errors as described in steps 1 and 2
  if (!blink::IsValidCustomHandlerScheme(protocol, security_level)) {
    return false;
  }

  blink::URLSyntaxErrorCode code =
      blink::IsValidCustomHandlerURLSyntax(url, security_level);
  if (code != blink::URLSyntaxErrorCode::kNoError) {
    return false;
  }

  // Verify custom handler URL security as described in steps 6 and 7
  if (!blink::IsAllowedCustomHandlerURL(url, security_level)) {
    return false;
  }
  url::Origin url_origin = url::Origin::Create(url);
  if (url_origin.opaque()) {
    return false;
  }
  if (security_level < blink::ProtocolHandlerSecurityLevel::kUntrustedOrigins &&
      !origin.IsSameOriginWith(url)) {
    return false;
  }

  return true;
}

void RecordMaxFrameCountUMA(size_t max_frame_count) {
  UMA_HISTOGRAM_COUNTS_10000("Navigation.MainFrame.MaxFrameCount",
                             max_frame_count);
}

// Returns the set of all WebContentses that are reachable from |web_contents|
// by applying some combination of
// WebContents::GetFirstWebContentsInLiveOriginalOpenerChain() and
// WebContents::GetOuterWebContents(). The |web_contents| parameter will be
// included in the returned set.
base::flat_set<WebContentsImpl*> GetAllOpeningWebContents(
    WebContentsImpl* web_contents) {
  base::flat_set<WebContentsImpl*> result;
  base::flat_set<WebContentsImpl*> current;

  current.insert(web_contents);

  while (!current.empty()) {
    WebContentsImpl* current_contents = *current.begin();
    current.erase(current.begin());
    auto insert_result = result.insert(current_contents);

    if (insert_result.second) {
      if (WebContents* opener_contents =
              current_contents
                  ->GetFirstWebContentsInLiveOriginalOpenerChain()) {
        current.insert(static_cast<WebContentsImpl*>(opener_contents));
      }

      WebContentsImpl* outer_contents = current_contents->GetOuterWebContents();
      if (outer_contents) {
        current.insert(outer_contents);
      }
    }
  }

  return result;
}

#if BUILDFLAG(IS_ANDROID)
float GetDeviceScaleAdjustment(int min_width) {
  static const float kMinFSM = 1.05f;
  static const int kWidthForMinFSM = 320;
  static const float kMaxFSM = 1.3f;
  static const int kWidthForMaxFSM = 800;

  if (min_width <= kWidthForMinFSM) {
    return kMinFSM;
  }
  if (min_width >= kWidthForMaxFSM) {
    return kMaxFSM;
  }

  // The font scale multiplier varies linearly between kMinFSM and kMaxFSM.
  float ratio = static_cast<float>(min_width - kWidthForMinFSM) /
                (kWidthForMaxFSM - kWidthForMinFSM);
  return ratio * (kMaxFSM - kMinFSM) + kMinFSM;
}
#endif

// Store a set of fullscreen WebContents and metadata for the browser context.
// Storing this information on the browser context is done for two reasons. One,
// related WebContentses must necessarily share a browser context, so this saves
// lookup time by restricting to one specific browser context. Two, separating
// by browser context is preemptive paranoia about keeping things separate.
class FullscreenUserData : public base::SupportsUserData::Data {
 public:
  FullscreenUserData() = default;
  ~FullscreenUserData() override = default;

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

  base::flat_set<raw_ptr<WebContentsImpl, CtnExperimental>>* set() {
    return &set_;
  }

  std::map<url::Origin, base::TimeTicks>* last_exits() { return &last_exits_; }

 private:
  base::flat_set<raw_ptr<WebContentsImpl, CtnExperimental>> set_;
  // Track latest exits by origin to briefly block re-entry without a gesture.
  std::map<url::Origin, base::TimeTicks> last_exits_;
};

const char kFullscreenUserData[] = "fullscreen-user-data";

FullscreenUserData* GetFullscreenUserData(BrowserContext* browser_context) {
  auto* set_holder = static_cast<FullscreenUserData*>(
      browser_context->GetUserData(kFullscreenUserData));
  if (!set_holder) {
    auto new_holder = std::make_unique<FullscreenUserData>();
    set_holder = new_holder.get();
    browser_context->SetUserData(kFullscreenUserData, std::move(new_holder));
  }
  return set_holder;
}

base::flat_set<raw_ptr<WebContentsImpl, CtnExperimental>>*
FullscreenContentsSet(BrowserContext* browser_context) {
  return GetFullscreenUserData(browser_context)->set();
}

// Returns true if `host` has the Window Management permission granted.
bool IsWindowManagementGranted(RenderFrameHost* host) {
  content::PermissionController* permission_controller =
      host->GetBrowserContext()->GetPermissionController();
  CHECK(permission_controller);

  return permission_controller->GetPermissionStatusForCurrentDocument(
             content::PermissionDescriptorUtil::
                 CreatePermissionDescriptorForPermissionType(
                     blink::PermissionType::WINDOW_MANAGEMENT),
             host) == blink::mojom::PermissionStatus::GRANTED;
}

// Returns true if `host` has the Automatic Fullscreen permission granted.
bool IsAutomaticFullscreenGranted(RenderFrameHost* host) {
  content::PermissionController* permission_controller =
      host->GetBrowserContext()->GetPermissionController();
  CHECK(permission_controller);

  return permission_controller->GetPermissionStatusForCurrentDocument(
             content::PermissionDescriptorUtil::
                 CreatePermissionDescriptorForPermissionType(
                     blink::PermissionType::AUTOMATIC_FULLSCREEN),
             host) == blink::mojom::PermissionStatus::GRANTED;
}

// Adjust the requested `rect` for opening or placing a window and return the id
// of the display where the window will be placed. The bounds may not extend
// outside a single screen's work area, and the `host` requires permission to
// specify bounds on a screen other than its current screen.
// TODO(crbug.com/40092782): These adjustments are inaccurate for window.open(),
// which specifies the inner content size, and for window.moveTo, resizeTo, etc.
// calls on newly created windows, which may pass empty sizes or positions to
// indicate uninitialized placement information in the renderer. Constraints
// enforced later should resolve most inaccuracies, but this early enforcement
// is needed to ensure bounds indicate the appropriate display.
int64_t AdjustWindowRectForDisplay(gfx::Rect* rect, RenderFrameHost* host) {
  auto* screen = display::Screen::Get();
  auto display = screen->GetDisplayMatching(*rect);

  // Check, but do not prompt, for permission to place windows on other screens.
  // Sites generally need permission to get such bounds in the first place.
  // Also clamp offscreen bounds to the window's current screen.
  if (!rect->Intersects(display.bounds()) || !IsWindowManagementGranted(host)) {
    // Use the main frame's NativeView; cross-origin iframes yield null.
    gfx::NativeView view = host->GetOutermostMainFrame()->GetNativeView();
    display = screen->GetDisplayNearestView(view);
  }
  rect->AdjustToFit(display.work_area());
  return display.id();
}

// Adjusts the bounds to the minimum window size provided. Defaults to
// `blink::kMinimumWindowSize` but can be overridden, e.g. for borderless apps.
void AdjustWindowRectForMinimum(gfx::Rect* bounds,
                                int minimum_size = blink::kMinimumWindowSize) {
  // Size 0 indicates default size, not minimum.
  if (bounds->width()) {
    bounds->set_width(std::max(minimum_size, bounds->width()));
  }
  if (bounds->height()) {
    bounds->set_height(std::max(minimum_size, bounds->height()));
  }
}

// A ColorProviderSource used when one has not been explicitly set. This source
// only reflects theme information present in the web NativeTheme singleton.
// Keep this an implementation detail of WebContentsImpl as we should not be
// exposing a default ColorProviderSource generally.
class DefaultColorProviderSource : public ui::ColorProviderSource,
                                   public ui::NativeThemeObserver {
 public:
  DefaultColorProviderSource() {
    native_theme_observation_.Observe(ui::NativeTheme::GetInstanceForWeb());
  }
  DefaultColorProviderSource(const DefaultColorProviderSource&) = delete;
  DefaultColorProviderSource& operator=(const DefaultColorProviderSource&) =
      delete;
  ~DefaultColorProviderSource() override = default;

  static DefaultColorProviderSource* GetInstance() {
    static base::NoDestructor<DefaultColorProviderSource> instance;
    return instance.get();
  }

  // ui::ColorProviderSource:
  const ui::ColorProvider* GetColorProvider() const override {
    return ui::ColorProviderManager::Get().GetColorProviderFor(
        GetColorProviderKey());
  }

  ui::RendererColorMap GetRendererColorMap(
      ui::ColorProviderKey::ColorMode color_mode,
      ui::ColorProviderKey::ForcedColors forced_colors) const override {
    auto key = GetColorProviderKey();
    key.color_mode = color_mode;
    key.forced_colors = forced_colors;
    ui::ColorProvider* color_provider =
        ui::ColorProviderManager::Get().GetColorProviderFor(key);
    CHECK(color_provider);

    return ui::CreateRendererColorMap(*color_provider);
  }

  // ui::NativeThemeObserver:
  void OnNativeThemeUpdated(ui::NativeTheme* observed_theme) override {
    DCHECK(native_theme_observation_.IsObservingSource(observed_theme));
    NotifyColorProviderChanged();
  }

 protected:
  // ui::ColorProviderSource:
  ui::ColorProviderKey GetColorProviderKey() const override {
    return ui::NativeTheme::GetInstanceForWeb()->GetColorProviderKey(nullptr);
  }

 private:
  base::ScopedObservation<ui::NativeTheme, ui::NativeThemeObserver>
      native_theme_observation_{this};
};

size_t GetFrameTreeSize(FrameTree* frame_tree) {
  size_t tree_size = 0;
  FrameTree::NodeRange node_range = frame_tree->NodesIncludingInnerTreeNodes();
  FrameTree::NodeIterator node_iter = node_range.begin();
  while (node_iter != node_range.end()) {
    // Skip over collapsed frame trees.
    if ((*node_iter)->is_collapsed()) {
      node_iter.AdvanceSkippingChildren();
    } else {
      ++tree_size;
      ++node_iter;
    }
  }
  return tree_size;
}

using RenderWidgetHostAtPointCallback =
    base::OnceCallback<void(base::WeakPtr<RenderWidgetHostViewBase>,
                            std::optional<gfx::PointF>)>;

void RunCallback(RenderWidgetHostAtPointCallback callback,
                 base::WeakPtr<input::RenderWidgetHostViewInput> view,
                 std::optional<gfx::PointF> point) {
  auto* target = static_cast<RenderWidgetHostViewBase*>(view.get());
  if (!callback.is_null()) {
    std::move(callback).Run(target ? target->GetWeakPtr() : nullptr, point);
  }
}

// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class RenderProcessHostPriority {
  kBestEffort = 0,
  kUserVisible = 1,
  kUserBlocking = 2,
  kMissingRenderProcessHost = 3,
  kMaxValue = kMissingRenderProcessHost,
};

RenderProcessHostPriority GetRenderProcessHostPriority(
    RenderProcessHost* render_process_host) {
  if (!render_process_host) {
    return RenderProcessHostPriority::kMissingRenderProcessHost;
  }
  switch (render_process_host->GetPriority()) {
    case base::Process::Priority::kBestEffort:
      return RenderProcessHostPriority::kBestEffort;
    case base::Process::Priority::kUserVisible:
      return RenderProcessHostPriority::kUserVisible;
    case base::Process::Priority::kUserBlocking:
      return RenderProcessHostPriority::kUserBlocking;
  }
  NOTREACHED();
}

void RecordRendererUnresponsiveMetrics(
    bool web_contents_visible,
    RenderWidgetHostImpl* render_widget_host) {
  base::UmaHistogramBoolean("Renderer.Unresponsive.Visibility",
                            web_contents_visible);

  if (!web_contents_visible) {
    return;
  }

  RenderProcessHostPriority rph_priority =
      GetRenderProcessHostPriority(render_widget_host->GetProcess());
  base::UmaHistogramEnumeration(
      "Renderer.Unresponsive.PageVisible.RenderProcessHostPriority",
      rph_priority);

  bool widget_visible = !render_widget_host->IsHidden();
  base::UmaHistogramBoolean(
      "Renderer.Unresponsive.PageVisible.WidgetVisibility", widget_visible);

  if (!widget_visible) {
    return;
  }

  base::UmaHistogramEnumeration(
      "Renderer.Unresponsive.WidgetVisible.RenderProcessHostPriority",
      rph_priority);
}

// Helper function to simplify getting the correct HostZoomMapImpl for a
// RenderFrameHost. Implemented here to be close to its only consumer,
// GetPendingZoomLevel().
HostZoomMapImpl* HostZoomMapForRenderFrameHost(const RenderFrameHost* rfh) {
  return static_cast<HostZoomMapImpl*>(
      HostZoomMap::Get(rfh->GetSiteInstance()));
}

}  // namespace

// This is a small helper class created while a JavaScript dialog is showing
// and destroyed when it's dismissed. Clients can register callbacks to receive
// a notification when the dialog is dismissed.
class JavaScriptDialogDismissNotifier {
 public:
  JavaScriptDialogDismissNotifier() = default;

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

  ~JavaScriptDialogDismissNotifier() {
    for (auto& callback : callbacks_) {
      std::move(callback).Run();
    }
  }

  void NotifyOnDismiss(base::OnceClosure callback) {
    callbacks_.push_back(std::move(callback));
  }

 private:
  std::vector<base::OnceClosure> callbacks_;
};

CreatedWindow::CreatedWindow() = default;
CreatedWindow::CreatedWindow(std::unique_ptr<WebContentsImpl> contents,
                             GURL target_url)
    : contents(std::move(contents)), target_url(std::move(target_url)) {}
CreatedWindow::~CreatedWindow() = default;
CreatedWindow::CreatedWindow(CreatedWindow&&) = default;
CreatedWindow& CreatedWindow::operator=(CreatedWindow&&) = default;

std::unique_ptr<WebContents> WebContents::Create(
    const WebContents::CreateParams& params) {
  return WebContentsImpl::Create(params);
}

std::unique_ptr<WebContentsImpl> WebContentsImpl::Create(
    const CreateParams& params) {
  return CreateWithOpener(params, FindOpenerRFH(params));
}

std::unique_ptr<WebContents> WebContents::CreateWithSessionStorage(
    const WebContents::CreateParams& params,
    const SessionStorageNamespaceMap& session_storage_namespace_map) {
  OPTIONAL_TRACE_EVENT0("content", "WebContents::CreateWithSessionStorage");
  std::unique_ptr<WebContentsImpl> new_contents(
      new WebContentsImpl(params.browser_context));
  RenderFrameHostImpl* opener_rfh = FindOpenerRFH(params);
  FrameTreeNode* opener = nullptr;
  if (opener_rfh) {
    opener = opener_rfh->frame_tree_node();
  }
  new_contents->SetOpenerForNewContents(opener, params.opener_suppressed);

  for (const auto& it : session_storage_namespace_map) {
    new_contents->GetController().SetSessionStorageNamespace(it.first,
                                                             it.second.get());
  }

  WebContentsImpl* outer_web_contents = nullptr;
  if (params.guest_delegate) {
    // This makes |new_contents| act as a guest.
    // For more info, see comment above class BrowserPluginGuest.
    BrowserPluginGuest::CreateInWebContents(new_contents.get(),
                                            params.guest_delegate);
    outer_web_contents = static_cast<WebContentsImpl*>(
        params.guest_delegate->GetOwnerWebContents());
  }

  new_contents->Init(params, blink::FramePolicy());
  if (outer_web_contents) {
    outer_web_contents->InnerWebContentsCreated(new_contents.get());
  }
  return new_contents;
}

base::CallbackListSubscription
WebContentsImpl::FriendWrapper::AddCreatedCallbackForTesting(
    const CreatedCallback& callback) {
  return g_created_callbacks.Get().Add(callback);
}

WebContents* WebContents::FromRenderViewHost(RenderViewHost* rvh) {
  OPTIONAL_TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("content.verbose"),
                        "WebContents::FromRenderViewHost", "render_view_host",
                        rvh);
  if (!rvh) {
    return nullptr;
  }
  return static_cast<WebContentsImpl*>(
      static_cast<RenderViewHostImpl*>(rvh)->GetDelegate());
}

WebContents* WebContents::FromRenderFrameHost(RenderFrameHost* rfh) {
  OPTIONAL_TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("content.verbose"),
                        "WebContents::FromRenderFrameHost", "render_frame_host",
                        rfh);
  return WebContentsImpl::FromRenderFrameHostImpl(
      static_cast<RenderFrameHostImpl*>(rfh));
}

WebContentsImpl* WebContentsImpl::FromRenderFrameHostImpl(
    RenderFrameHostImpl* rfh) {
  OPTIONAL_TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("content.verbose"),
                        "WebContentsImpl::FromRenderFrameHostImpl",
                        "render_frame_host", rfh);
  if (!rfh) {
    return nullptr;
  }
  return static_cast<WebContentsImpl*>(rfh->delegate());
}

WebContents* WebContents::FromFrameTreeNodeId(
    FrameTreeNodeId frame_tree_node_id) {
  OPTIONAL_TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("content.verbose"),
                        "WebContents::FromFrameTreeNodeId",
                        "frame_tree_node_id", frame_tree_node_id);
  FrameTreeNode* frame_tree_node =
      FrameTreeNode::GloballyFindByID(frame_tree_node_id);
  if (!frame_tree_node) {
    return nullptr;
  }
  return WebContentsImpl::FromFrameTreeNode(frame_tree_node);
}

WebContentsImpl* WebContentsImpl::FromRenderWidgetHostImpl(
    RenderWidgetHostImpl* rwh) {
  if (!rwh) {
    return nullptr;
  }
  return static_cast<WebContentsImpl*>(rwh->delegate());
}

bool WebContentsImpl::IsPopup() const {
  return is_popup_;
}

bool WebContentsImpl::IsPartitionedPopin() const {
  // The feature must be enabled if a popin was opened.
  CHECK(base::FeatureList::IsEnabled(blink::features::kPartitionedPopins) ||
        (!partitioned_popin_opener_ && !partitioned_popin_opener_properties_));

  // We must check local data and not `partitioned_popin_opener_` as it could
  // go away before this popin closes.
  return !!partitioned_popin_opener_properties_;
}

const PartitionedPopinOpenerProperties&
WebContentsImpl::GetPartitionedPopinOpenerProperties() const {
  // This function is only usable if we are in a popin.
  CHECK(IsPartitionedPopin());

  return *partitioned_popin_opener_properties_;
}

RenderFrameHostImpl* WebContentsImpl::GetPartitionedPopinOpener(
    base::PassKey<PartitionedPopinsController>) const {
  // A popin cannot open a popin so at most one could be set at a time.
  CHECK(!partitioned_popin_opener_ || !opened_partitioned_popin_);

  // The feature must be enabled if the popin opener is set.
  CHECK(base::FeatureList::IsEnabled(blink::features::kPartitionedPopins) ||
        !partitioned_popin_opener_);

  return partitioned_popin_opener_.get();
}

void WebContentsImpl::ClearPartitionedPopinOpenerForTesting() {
  partitioned_popin_opener_.reset();
}

WebContents* WebContentsImpl::GetOpenedPartitionedPopin() const {
  // A popin cannot open a popin so at most one could be set at a time.
  CHECK(!IsPartitionedPopin() || !opened_partitioned_popin_);

  // The feature must be enabled if a popin was opened.
  CHECK(base::FeatureList::IsEnabled(blink::features::kPartitionedPopins) ||
        !opened_partitioned_popin_);

  return opened_partitioned_popin_.get();
}

GURL WebContentsImpl::GetPartitionedPopinEmbedderOrigin(
    base::PassKey<StorageAccessGrantPermissionContext>) const {
  return GetPartitionedPopinEmbedderOriginImpl();
}

GURL WebContentsImpl::GetPartitionedPopinEmbedderOriginForTesting() const {
  return GetPartitionedPopinEmbedderOriginImpl();
}

GURL WebContentsImpl::GetPartitionedPopinEmbedderOriginImpl() const {
  // This should only be checked for popins.
  CHECK(IsPartitionedPopin());

  // If the opener is still around and has not navigated then we want to use the
  // embedder origin it would have used for its own iframe.
  if (partitioned_popin_opener_ &&
      partitioned_popin_opener_->GetMainFrame()->GetLastCommittedOrigin() ==
          partitioned_popin_opener_properties_->top_frame_origin) {
    return PermissionUtil::GetLastCommittedOriginAsURL(
        partitioned_popin_opener_->GetMainFrame());
  }
  // If we end up here there was a race condition between a permissions check
  // and this popin being closed or navigated, so we should fallback to using
  // the origin we partitioned by.
  return partitioned_popin_opener_properties_->top_frame_origin.GetURL();
}

WindowOpenDisposition WebContentsImpl::GetOriginalWindowOpenDisposition()
    const {
  return original_window_open_disposition_;
}

void WebContents::SetScreenOrientationDelegate(
    ScreenOrientationDelegate* delegate) {
  ScreenOrientationProvider::SetDelegate(delegate);
}

// WebContentsImpl::RenderWidgetHostDestructionObserver -----------------------

class WebContentsImpl::RenderWidgetHostDestructionObserver
    : public RenderWidgetHostObserver {
 public:
  RenderWidgetHostDestructionObserver(WebContentsImpl* owner,
                                      RenderWidgetHost* watched_host)
      : owner_(owner), watched_host_(watched_host) {
    watched_host_->AddObserver(this);
  }

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

  ~RenderWidgetHostDestructionObserver() override {
    watched_host_->RemoveObserver(this);
  }

  // RenderWidgetHostObserver:
  void RenderWidgetHostDestroyed(RenderWidgetHost* widget_host) override {
    owner_->OnRenderWidgetHostDestroyed(widget_host);
  }

 private:
  raw_ptr<WebContentsImpl> owner_;
  raw_ptr<RenderWidgetHost> watched_host_;
};

// WebContentsImpl::WebContentsDestructionObserver ----------------------------

class WebContentsImpl::WebContentsDestructionObserver
    : public WebContentsObserver {
 public:
  WebContentsDestructionObserver(WebContentsImpl* owner,
                                 WebContents* watched_contents)
      : WebContentsObserver(watched_contents), owner_(owner) {}

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

  // WebContentsObserver:
  void WebContentsDestroyed() override {
    owner_->OnWebContentsDestroyed(
        static_cast<WebContentsImpl*>(web_contents()));
  }

 private:
  raw_ptr<WebContentsImpl> owner_;
};

#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
// TODO(sreejakshetty): Make |WebContentsImpl::ColorChooserHolder| per-frame
// instead of WebContents-owned.
// WebContentsImpl::ColorChooserHolder -----------------------------------------
class WebContentsImpl::ColorChooserHolder : public blink::mojom::ColorChooser {
 public:
  ColorChooserHolder(
      mojo::PendingReceiver<blink::mojom::ColorChooser> receiver,
      mojo::PendingRemote<blink::mojom::ColorChooserClient> client)
      : receiver_(this, std::move(receiver)), client_(std::move(client)) {}

  ~ColorChooserHolder() override {
    if (chooser_) {
      chooser_->End();
    }
  }

  void SetChooser(std::unique_ptr<content::ColorChooser> chooser) {
    chooser_ = std::move(chooser);
    if (chooser_) {
      receiver_.set_disconnect_handler(
          base::BindOnce([](content::ColorChooser* chooser) { chooser->End(); },
                         base::Unretained(chooser_.get())));
    }
  }

  void SetSelectedColor(SkColor color) override {
    OPTIONAL_TRACE_EVENT0(
        "content", "WebContentsImpl::ColorChooserHolder::SetSelectedColor");
    if (chooser_) {
      chooser_->SetSelectedColor(color);
    }
  }

  void DidChooseColorInColorChooser(SkColor color) {
    OPTIONAL_TRACE_EVENT0(
        "content",
        "WebContentsImpl::ColorChooserHolder::DidChooseColorInColorChooser");
    client_->DidChooseColor(color);
  }

 private:
  // Color chooser that was opened by this tab.
  std::unique_ptr<content::ColorChooser> chooser_;

  // mojo receiver.
  mojo::Receiver<blink::mojom::ColorChooser> receiver_;

  // mojo renderer client.
  mojo::Remote<blink::mojom::ColorChooserClient> client_;
};
#endif  // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)

// WebContentsImpl::WebContentsTreeNode ----------------------------------------
WebContentsImpl::WebContentsTreeNode::WebContentsTreeNode(
    WebContentsImpl* current_web_contents)
    : current_web_contents_(current_web_contents),
      outer_web_contents_(nullptr) {}

WebContentsImpl::WebContentsTreeNode::~WebContentsTreeNode() = default;

void WebContentsImpl::WebContentsTreeNode::AttachInnerWebContents(
    WebContents* inner_web_contents,
    RenderFrameHostImpl* render_frame_host,
    bool should_take_ownership) {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsTreeNode::AttachInnerWebContents");
  WebContentsImpl* inner_web_contents_impl =
      static_cast<WebContentsImpl*>(inner_web_contents);
  WebContentsTreeNode& inner_web_contents_node = inner_web_contents_impl->node_;

  inner_web_contents_node.outer_web_contents_ = current_web_contents_;
  inner_web_contents_node.outer_contents_frame_tree_node_id_ =
      render_frame_host->frame_tree_node()->frame_tree_node_id();

  if (should_take_ownership) {
    inner_web_contents->SetOwnerLocationForDebug(FROM_HERE);
    owned_inner_web_contents_.push_back(base::WrapUnique(inner_web_contents));
  } else {
    unowned_inner_web_contents_.push_back(inner_web_contents);
  }

  render_frame_host->frame_tree_node()->AddObserver(&inner_web_contents_node);
  current_web_contents_->InnerWebContentsAttached(inner_web_contents_impl);
}

void WebContentsImpl::WebContentsTreeNode::DetachInnerWebContents(
    WebContents* inner_web_contents) {
  OPTIONAL_TRACE_EVENT0(
      "content",
      "WebContentsImpl::WebContentsTreeNode::DetachInnerWebContents");
  CHECK_EQ(inner_web_contents->GetOuterWebContents(), current_web_contents_);

  auto* inner_web_contents_impl =
      static_cast<WebContentsImpl*>(inner_web_contents);
  if (IsUnownedInnerWebContents(inner_web_contents)) {
    DetachUnownedInnerWebContents(inner_web_contents_impl);
  } else {
    DestroyOwnedInnerWebContents(inner_web_contents_impl);
  }
}

bool WebContentsImpl::WebContentsTreeNode::IsUnownedInnerWebContents(
    WebContents* inner_web_contents) const {
  CHECK_EQ(inner_web_contents->GetOuterWebContents(), current_web_contents_);
  return base::Contains(unowned_inner_web_contents_, inner_web_contents);
}

void WebContentsImpl::WebContentsTreeNode::DetachUnownedInnerWebContents(
    WebContentsImpl* inner_web_contents) {
  std::erase(unowned_inner_web_contents_, inner_web_contents);

  // Detach WebContents tree node and frame tree node.
  bool was_inner_web_contents_focused =
      inner_web_contents->ContainsOrIsFocusedWebContents();
  FrameTree* focused_frame_tree = inner_web_contents->GetFocusedFrameTree();
  WebContentsTreeNode& inner_web_contents_node = inner_web_contents->node_;
  inner_web_contents_node.outer_web_contents_ = nullptr;
  FrameTreeNode* outer_contents_frame_tree_node =
      inner_web_contents_node.OuterContentsFrameTreeNode();
  outer_contents_frame_tree_node->RemoveObserver(&inner_web_contents_node);
  outer_contents_frame_tree_node->current_frame_host()
      ->set_inner_tree_main_frame_tree_node_id(FrameTreeNodeId());
  outer_contents_frame_tree_node->render_manager()
      ->set_detach_inner_delegate_complete();
  inner_web_contents_node.outer_contents_frame_tree_node_id_ =
      FrameTreeNodeId();

  // Reset inner WebContents's focused frame tree.
  // When attached, only the outermost WebContents retains a focused tree. After
  // detaching, the inner WebContents becomes the outermost WebContents from its
  // perspective, so its focused frame tree needs to be set.
  inner_web_contents_node.SetFocusedFrameTree(
      was_inner_web_contents_focused
          ? focused_frame_tree
          : &inner_web_contents->GetPrimaryFrameTree());
  // Reset the outermost WebContents's focused frame tree if the inner
  // WebContents was focused before detaching.
  if (was_inner_web_contents_focused) {
    current_web_contents_->SetAsFocusedWebContentsIfNecessary();
  }

  current_web_contents_->InnerWebContentsDetached(inner_web_contents);
}

void WebContentsImpl::WebContentsTreeNode::DestroyOwnedInnerWebContents(
    WebContentsImpl* inner_web_contents) {
  std::unique_ptr<WebContents> inner_web_contents_to_delete;
  for (std::unique_ptr<WebContents>& web_contents : owned_inner_web_contents_) {
    if (web_contents.get() == inner_web_contents) {
      // Remove the WebContents from the list of owned WebContents.
      inner_web_contents_to_delete = std::move(web_contents);
      std::swap(web_contents, owned_inner_web_contents_.back());
      owned_inner_web_contents_.pop_back();
      break;
    }
  }
  CHECK(inner_web_contents_to_delete);
  inner_web_contents->SetOwnerLocationForDebug(std::nullopt);
  current_web_contents_->InnerWebContentsDetached(inner_web_contents);
  inner_web_contents_to_delete.reset();
}

FrameTreeNode*
WebContentsImpl::WebContentsTreeNode::OuterContentsFrameTreeNode() const {
  return FrameTreeNode::GloballyFindByID(outer_contents_frame_tree_node_id_);
}

void WebContentsImpl::WebContentsTreeNode::OnFrameTreeNodeDestroyed(
    FrameTreeNode* node) {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsTreeNode::OnFrameTreeNodeDestroyed");
  DCHECK_EQ(outer_contents_frame_tree_node_id_, node->frame_tree_node_id())
      << "WebContentsTreeNode should only receive notifications for the "
         "FrameTreeNode in its outer WebContents that hosts it.";

  node->RemoveObserver(this);

  if (outer_web_contents_->node_.IsUnownedInnerWebContents(
          current_web_contents_)) {
    // Detach at all levels (WebContentsTreeNode and FrameTreeNode,
    // RenderFrameProxyHost, etc.). This will not delete `this` (the inner
    // WebContents).
    outer_web_contents_->DetachUnownedInnerWebContents(current_web_contents_);
  } else {
    // Detach only at the WebContentsTreeNode level. This will delete `this` (
    // the inner WebContents).
    outer_web_contents_->node_.DetachInnerWebContents(current_web_contents_);
  }
}

FrameTree* WebContentsImpl::WebContentsTreeNode::focused_frame_tree() {
  CHECK(focused_frame_tree_);
  return focused_frame_tree_;
}

void WebContentsImpl::WebContentsTreeNode::SetFocusedFrameTree(
    FrameTree* frame_tree) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsTreeNode::SetFocusedFrameTree");
  DCHECK(!outer_web_contents())
      << "Only the outermost WebContents tracks focus.";
  focused_frame_tree_ = frame_tree;
}

WebContentsImpl*
WebContentsImpl::WebContentsTreeNode::GetInnerWebContentsInFrame(
    const FrameTreeNode* frame) {
  auto ftn_id = frame->frame_tree_node_id();
  for (auto& contents : owned_inner_web_contents_) {
    WebContentsImpl* impl = static_cast<WebContentsImpl*>(contents.get());
    if (impl->node_.outer_contents_frame_tree_node_id() == ftn_id) {
      return impl;
    }
  }
  for (auto& contents : unowned_inner_web_contents_) {
    WebContentsImpl* impl = static_cast<WebContentsImpl*>(contents);
    if (impl->node_.outer_contents_frame_tree_node_id() == ftn_id) {
      return impl;
    }
  }
  return nullptr;
}

std::vector<WebContentsImpl*>
WebContentsImpl::WebContentsTreeNode::GetInnerWebContents() const {
  std::vector<WebContentsImpl*> inner_web_contents;
  for (auto& contents : owned_inner_web_contents_) {
    inner_web_contents.push_back(static_cast<WebContentsImpl*>(contents.get()));
  }
  for (auto& contents : unowned_inner_web_contents_) {
    inner_web_contents.push_back(static_cast<WebContentsImpl*>(contents));
  }

  return inner_web_contents;
}

// WebContentsObserverList -----------------------------------------------------
WebContentsImpl::WebContentsObserverList::WebContentsObserverList() = default;
WebContentsImpl::WebContentsObserverList::~WebContentsObserverList() = default;

void WebContentsImpl::WebContentsObserverList::AddObserver(
    WebContentsObserver* observer) {
  observers_.AddObserver(observer);
}

void WebContentsImpl::WebContentsObserverList::RemoveObserver(
    WebContentsObserver* observer) {
  observers_.RemoveObserver(observer);
}

// WebContentsImpl -------------------------------------------------------------

namespace {

// A helper for ensuring that WebContents are closed (or otherwise destroyed)
// *before* their BrowserContext is destroyed.
class WebContentsOfBrowserContext : public base::SupportsUserData::Data {
 public:
  static void Attach(WebContentsImpl& web_contents) {
    WebContentsOfBrowserContext* self =
        GetOrCreate(*web_contents.GetBrowserContext());
    self->web_contents_set_.insert(&web_contents);
  }

  static void Detach(WebContentsImpl& web_contents) {
    WebContentsOfBrowserContext* self =
        GetOrCreate(*web_contents.GetBrowserContext());
    self->web_contents_set_.erase(&web_contents);
  }

  ~WebContentsOfBrowserContext() override {
    // The ~WebContentsOfBrowserContext destructor is called when the
    // BrowserContext (and its UserData) gets destroyed.  At this point
    // in time all the WebContents of this BrowserContext should have been
    // already closed (i.e. we expect the `web_contents_set_` set to be empty at
    // this point - emptied by calls to the `Detach` method above).
    if (web_contents_set_.empty()) {
      return;  // Everything is okay - nothing to warn about.
    }

    // Any remaining WebContents contain dangling pointers to the
    // BrowserContext being destroyed.  Such WebContents (and their
    // RenderFrameHosts, SiteInstances, etc.) risk causing
    // use-after-free bugs.  For more discussion about managing the
    // lifetime of WebContents please see https://crbug.com/1376879#c44.
    WebContentsImpl* const web_contents_with_dangling_ptr_to_browser_context =
        *web_contents_set_.begin();
    const std::string creator =
        web_contents_with_dangling_ptr_to_browser_context->GetCreatorLocation()
            .ToString();
    SCOPED_CRASH_KEY_STRING256("shutdown", "web_contents/creator", creator);

    const std::optional<base::Location>& ownership_location =
        web_contents_with_dangling_ptr_to_browser_context->ownership_location();
    std::string owner;
    if (ownership_location) {
      if (ownership_location->has_source_info()) {
        owner = std::string(ownership_location->function_name()) + "@" +
                ownership_location->file_name();
      } else {
        owner = "no_source_info";
      }
    } else {
      owner = "unknown";
    }
    SCOPED_CRASH_KEY_STRING256("shutdown", "web_contents/owner", owner);

#if BUILDFLAG(IS_ANDROID)
    // On Android, also report the Java stack trace from WebContents's
    // creation.
    WebContentsAndroid::ReportDanglingPtrToBrowserContext(
        base::android::AttachCurrentThread(),
        web_contents_with_dangling_ptr_to_browser_context);
#endif  // BUILDFLAG(IS_ANDROID)

    NOTREACHED()
        << "BrowserContext is getting destroyed without first closing all "
        << "WebContents (for more info see https://crbug.com/1376879#c44); "
        << "creator = " << creator;
  }

  std::unique_ptr<Data> Clone() override {
    // Indicate to `SupportsUserData` / `BrowserContext` that cloning is not
    // supported.
    return nullptr;
  }

 private:
  WebContentsOfBrowserContext() = default;

  // Gets WebContentsOfBrowserContext associated with the given
  // `browser_context` (creating a new WebContentsOfBrowserContext if
  // necessary - if one hasn't been created yet).
  static WebContentsOfBrowserContext* GetOrCreate(
      BrowserContext& browser_context) {
    static const char* kUserDataKey = "WebContentsOfBrowserContext/UserDataKey";
    WebContentsOfBrowserContext* result =
        static_cast<WebContentsOfBrowserContext*>(
            browser_context.GetUserData(kUserDataKey));
    if (!result) {
      result = new WebContentsOfBrowserContext();
      browser_context.SetUserData(kUserDataKey, base::WrapUnique(result));
    }
    return result;
  }

  // Set of all `WebContents` within the tracked `BrowserContext`.
  //
  // Usage of `raw_ptr` below is okay (i.e. it shouldn't dangle), because
  // when `WebContentsImpl`'s destructor runs, then it removes the set entry
  // (by calling `Detach`).
  std::set<raw_ptr<WebContentsImpl>> web_contents_set_;
};

}  // namespace

WebContentsImpl::WebContentsImpl(BrowserContext* browser_context)
    : ColorProviderSourceObserver(DefaultColorProviderSource::GetInstance()),
      delegate_(nullptr),
      render_view_host_delegate_view_(nullptr),
      opened_by_another_window_(false),
      node_(this),
      primary_frame_tree_(browser_context,
                          this,
                          this,
                          this,
                          this,
                          this,
                          this,
                          this,
                          this,
                          FrameTree::Type::kPrimary),
      primary_main_frame_process_status_(
          base::TERMINATION_STATUS_STILL_RUNNING),
      primary_main_frame_process_error_code_(0),
      load_state_(net::LOAD_STATE_IDLE, std::u16string()),
      upload_size_(0),
      upload_position_(0),
      is_resume_pending_(false),
      notify_disconnection_(false),
      is_showing_before_unload_dialog_(false),
      last_active_time_ticks_(base::TimeTicks::Now()),
      last_active_time_(base::Time::Now()),
      closed_by_user_gesture_(false),
      minimum_zoom_percent_(
          static_cast<int>(blink::kMinimumBrowserZoomFactor * 100)),
      maximum_zoom_percent_(
          static_cast<int>(blink::kMaximumBrowserZoomFactor * 100)),
      zoom_scroll_remainder_(0),
      force_disable_overscroll_content_(false),
      last_dialog_suppressed_(false),
      audio_stream_monitor_(this),
      media_web_contents_observer_(
          std::make_unique<MediaWebContentsObserver>(this)),
      is_overlay_content_(false),
      showing_context_menu_(false),
      prerender_host_registry_(std::make_unique<PrerenderHostRegistry>(*this)),
      compositor_frame_sink_grouping_id_(base::UnguessableToken::Create()),
      fenced_frame_viewport_observer_(
          std::make_unique<FencedFrameViewportObserver>(this)) {
  TRACE_EVENT0("content", "WebContentsImpl::WebContentsImpl");
  WebContentsOfBrowserContext::Attach(*this);
  node_.SetFocusedFrameTree(&primary_frame_tree_);
#if BUILDFLAG(IS_ANDROID)
  safe_area_insets_host_ = SafeAreaInsetsHost::Create(this);
#endif

  auto* const native_theme = ui::NativeTheme::GetInstanceForWeb();
  native_theme_observation_.Observe(native_theme);
  slow_web_preference_cache_observation_.Observe(
      SlowWebPreferenceCache::GetInstance());
  renderer_preferences_.caret_blink_interval =
      native_theme->caret_blink_interval();
#if BUILDFLAG(IS_CHROMEOS)
  renderer_preferences_.use_overlay_scrollbar =
      native_theme->use_overlay_scrollbar();
#endif

  screen_change_monitor_ =
      std::make_unique<ScreenChangeMonitor>(base::BindRepeating(
          &WebContentsImpl::OnScreensChange, base::Unretained(this)));

  if (base::FeatureList::IsEnabled(network::features::kSharedStorageAPI)) {
    SharedStorageBudgetCharger::CreateForWebContents(this);
  }
}

WebContentsImpl::~WebContentsImpl() {
  TRACE_EVENT0("content", "WebContentsImpl::~WebContentsImpl");
  WebContentsOfBrowserContext::Detach(*this);

  // Imperfect sanity check against double free, given some crashes unexpectedly
  // observed in the wild.
  CHECK(!IsBeingDestroyed());

  // We generally keep track of is_being_destroyed_ to let other features know
  // to avoid certain actions during destruction.
  is_being_destroyed_ = true;

  // A WebContents should never be deleted while it is notifying observers,
  // since this will lead to a use-after-free as it continues to notify later
  // observers.
  CHECK(!observers_.is_notifying_observers());
  // This is used to watch for one-off observers (i.e. non-WebContentsObservers)
  // destroying WebContents, which they should not do.
  CHECK(!prevent_destruction_);

  // We usually record `max_loaded_frame_count_` in `DidFinishNavigation()`
  // for pages the user navigated away from other than the last one. We record
  // it for the last page here.
  if (first_primary_navigation_completed_) {
    RecordMaxFrameCountUMA(max_loaded_frame_count_);
  }

  FullscreenContentsSet(GetBrowserContext())->erase(this);

  touch_emulator_.reset();

  rwh_input_event_router_.reset();

  WebContentsImpl* outermost = GetOutermostWebContents();
  if (this != outermost && ContainsOrIsFocusedWebContents()) {
    // If the current WebContents is in focus, unset it.
    outermost->SetAsFocusedWebContentsIfNecessary();
  }

  if (GetOuterWebContents() &&
      GetOuterWebContents()->node_.IsUnownedInnerWebContents(this)) {
    GetOuterWebContents()->DetachUnownedInnerWebContents(this);
  }

  if (pointer_lock_widget_) {
    pointer_lock_widget_->RejectPointerLockOrUnlockIfNecessary(
        blink::mojom::PointerLockResult::kElementDestroyed);

    // Normally, the call above clears mouse_lock_widget_ pointers on the
    // entire WebContents chain, since it results in calling LostPointerLock()
    // when the mouse lock is already active. However, this doesn't work for
    // <webview> guests if the mouse lock request is still pending while the
    // <webview> is destroyed. Hence, ensure that all mouse lock widget
    // pointers are cleared. See https://crbug.com/1346245.
    for (WebContentsImpl* current = this; current;
         current = current->GetOuterWebContents()) {
      current->pointer_lock_widget_ = nullptr;
    }
  }

  for (auto& itr : created_widgets_) {
    itr.second->DetachDelegate();
  }
  created_widgets_.clear();

  // Clear out any JavaScript state.
  CancelDialogManagerDialogs(/*reset_state=*/true);

#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
  color_chooser_holder_.reset();
#endif
  find_request_manager_.reset();

  // crbug.com/373898450: The `FrameTree` should outlive the animation manager.
  if (view_) {
    view_->DestroyBackForwardTransitionAnimationManager();
  }

  // Shutdown the primary FrameTree.
  primary_frame_tree_.Shutdown();

  // Shutdown the non-primary FrameTrees.
  //
  // Do this here rather than relying on the owner of the FrameTree to shutdown
  // on WebContentsDestroyed(), so that all the FrameTrees are shutdown at the
  // same time for consistency. Also, destroying a FrameTree results in other
  // observer functions like RenderFrameDeleted() being called, which are not
  // expected to be called after WebContentsDestroyed().
  //
  // Currently the only instances of the non-primary FrameTrees are for
  // prerendering. Shutdown them by destructing PrerenderHostRegistry.
  prerender_host_registry_.reset();

  // If audio is playing then notify external observers of the audio stream
  // disappearing.
  if (is_currently_audible_) {
    is_currently_audible_ = false;
    observers_.NotifyObservers(&WebContentsObserver::OnAudioStateChanged,
                               false);
    if (GetOuterWebContents()) {
      GetOuterWebContents()->OnAudioStateChanged();
    }
  }

  // |save_package_| is refcounted so make sure we clear the page before
  // we toss out our reference.
  if (save_package_) {
    save_package_->ClearPage();
  }

  observers_.NotifyObservers(&WebContentsObserver::WebContentsDestroyed);

#if BUILDFLAG(IS_ANDROID)
  // Destroy the WebContentsAndroid here, so that its observers still can access
  // `this`.
  ClearWebContentsAndroid();
#endif

  observers_.NotifyObservers(&WebContentsObserver::ResetWebContents);
  SetDelegate(nullptr);
}

std::unique_ptr<WebContentsImpl> WebContentsImpl::CreateWithOpener(
    const WebContents::CreateParams& params,
    RenderFrameHostImpl* opener_rfh) {
  OPTIONAL_TRACE_EVENT1("browser", "WebContentsImpl::CreateWithOpener",
                        "opener", opener_rfh);
  FrameTreeNode* opener = nullptr;
  if (opener_rfh) {
    opener = opener_rfh->frame_tree_node();
  }
  std::unique_ptr<WebContentsImpl> new_contents(
      new WebContentsImpl(params.browser_context));
  new_contents->SetOpenerForNewContents(opener, params.opener_suppressed);

  // If the opener is sandboxed, a new popup must inherit the opener's sandbox
  // flags, and these flags take effect immediately.  An exception is if the
  // opener's sandbox flags lack the PropagatesToAuxiliaryBrowsingContexts
  // bit (which is controlled by the "allow-popups-to-escape-sandbox" token).
  // See https://html.spec.whatwg.org/C/#attr-iframe-sandbox.
  FrameTreeNode* new_root = new_contents->GetPrimaryFrameTree().root();
  if (opener) {
    network::mojom::WebSandboxFlags opener_flags =
        opener_rfh->active_sandbox_flags();
    if (opener_rfh->IsSandboxed(network::mojom::WebSandboxFlags::
                                    kPropagatesToAuxiliaryBrowsingContexts)) {
      new_root->SetPendingFramePolicy(
          {opener_flags,
           {} /* container_policy */,
           {} /* required_document_policy */,
           blink::mojom::DeferredFetchPolicy::kDisabled});
    }
    new_root->SetInitialPopupURL(params.initial_popup_url);
    new_root->SetPopupCreatorOrigin(opener_rfh->GetLastCommittedOrigin());
  }

  // Apply starting sandbox flags.
  blink::FramePolicy frame_policy(new_root->pending_frame_policy());
  frame_policy.sandbox_flags |= params.starting_sandbox_flags;
  new_root->SetPendingFramePolicy(frame_policy);

  // This may be true even when opener is null, such as when opening blocked
  // popups.
  if (params.opened_by_another_window) {
    new_contents->opened_by_another_window_ = true;
  }

  WebContentsImpl* outer_web_contents = nullptr;
  if (params.guest_delegate) {
    // This makes |new_contents| act as a guest.
    // For more info, see comment above class BrowserPluginGuest.
    BrowserPluginGuest::CreateInWebContents(new_contents.get(),
                                            params.guest_delegate);
    outer_web_contents = static_cast<WebContentsImpl*>(
        params.guest_delegate->GetOwnerWebContents());
  }

  // Multi-network CCT relies on the following invariant: WebContents associated
  // with a CCT tab targeting a network will always have
  // WebContents::GetTargetNetwork == that target network. We MUST set the
  // target_network before WebContents initialization. Otherwise, the renderer,
  // during WebContents initialization, might create (and keep around)
  // URLLoaderFactories that won't load resources from the target network. For
  // WebContents created from Java (e.g., WebContents rendering a CCT), this is
  // guaranteed by the Java side setting
  // WebContents::CreateParams::target_network_ when that CCT is targeting a
  // network.
  new_contents->target_network_ = params.target_network;
  if (new_contents->target_network_ == net::handles::kInvalidNetworkHandle) {
    // For WebContents opened by another WebContents (e.g. through
    // window.open(), instead of from the UI / by the embedder),
    // WebContents::CreateParams::target_network_ won't be set, as the calling
    // code is not aware of multi-network CCT. Instead, to handle that, we pass
    // along the target network (if present) of the WebContents associated with
    // the opener frame.
    auto* web_contents = WebContentsImpl::FromRenderFrameHostImpl(opener_rfh);
    if (web_contents) {
      new_contents->target_network_ = web_contents->GetTargetNetwork();
    }
  }

  new_contents->Init(params, frame_policy);
  if (outer_web_contents) {
    outer_web_contents->InnerWebContentsCreated(new_contents.get());
  }
  return new_contents;
}

// static
std::vector<WebContentsImpl*> WebContentsImpl::GetAllWebContents() {
  OPTIONAL_TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("content.verbose"),
                        "WebContentsImpl::GetAllWebContents");
  std::vector<WebContentsImpl*> result;
  std::unique_ptr<RenderWidgetHostIterator> widgets(
      RenderWidgetHostImpl::GetRenderWidgetHosts());
  while (RenderWidgetHost* rwh = widgets->GetNextHost()) {
    RenderViewHost* rvh = RenderViewHost::From(rwh);
    if (!rvh) {
      continue;
    }
    WebContents* web_contents = WebContents::FromRenderViewHost(rvh);
    if (!web_contents || web_contents->IsBeingDestroyed()) {
      continue;
    }
    if (web_contents->GetPrimaryMainFrame()->GetRenderViewHost() != rvh) {
      continue;
    }
    // Because a WebContents can only have one current RVH at a time, there will
    // be no duplicate WebContents here.
    result.push_back(static_cast<WebContentsImpl*>(web_contents));
  }
  return result;
}

// static
WebContentsImpl* WebContentsImpl::FromFrameTreeNode(
    const FrameTreeNode* frame_tree_node) {
  OPTIONAL_TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("content.verbose"),
                        "WebContentsImpl::FromFrameTreeNode", "frame_tree_node",
                        static_cast<const void*>(frame_tree_node));
  return static_cast<WebContentsImpl*>(
      WebContents::FromRenderFrameHost(frame_tree_node->current_frame_host()));
}

// static
WebContents* WebContentsImpl::FromRenderFrameHostID(
    GlobalRenderFrameHostId render_frame_host_id) {
  OPTIONAL_TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("content.verbose"),
                        "WebContentsImpl::FromRenderFrameHostID", "process_id",
                        render_frame_host_id.child_id, "frame_id",
                        render_frame_host_id.frame_routing_id);
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) ||
         !BrowserThread::IsThreadInitialized(BrowserThread::UI));
  RenderFrameHost* render_frame_host =
      RenderFrameHost::FromID(render_frame_host_id);
  if (!render_frame_host) {
    return nullptr;
  }

  return WebContents::FromRenderFrameHost(render_frame_host);
}

// static
WebContents* WebContentsImpl::FromRenderFrameHostID(int render_process_host_id,
                                                    int render_frame_host_id) {
  return FromRenderFrameHostID(
      GlobalRenderFrameHostId(render_process_host_id, render_frame_host_id));
}

// static
WebContentsImpl* WebContentsImpl::FromOuterFrameTreeNode(
    const FrameTreeNode* frame_tree_node) {
  OPTIONAL_TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("content.verbose"),
                        "WebContentsImpl::FromOuterFrameTreeNode",
                        "frame_tree_node",
                        static_cast<const void*>(frame_tree_node));
  return WebContentsImpl::FromFrameTreeNode(frame_tree_node)
      ->node_.GetInnerWebContentsInFrame(frame_tree_node);
}

std::string WebContentsImpl::GetTitleForMediaControls() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::GetTitleForMediaControls");

  if (!delegate_) {
    return std::string();
  }
  return delegate_->GetTitleForMediaControls(this);
}

// Returns the NavigationController for the primary FrameTree, i.e. the one
// whose URL is shown in the omnibox. With MPArch we can have multiple
// FrameTrees in one WebContents and each has its own NavigationController.
// TODO(crbug.com/40165692): Make sure callers are aware of this.
NavigationControllerImpl& WebContentsImpl::GetController() {
  return primary_frame_tree_.controller();
}

const NavigationControllerImpl& WebContentsImpl::GetController() const {
  return primary_frame_tree_.controller();
}

BrowserContext* WebContentsImpl::GetBrowserContext() {
  return GetController().GetBrowserContext();
}

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

const GURL& WebContentsImpl::GetURL() {
  return GetVisibleURL();
}

const GURL& WebContentsImpl::GetVisibleURL() {
  // We may not have a navigation entry yet.
  NavigationEntry* entry = GetController().GetVisibleEntry();
  return entry ? entry->GetVirtualURL() : GURL::EmptyGURL();
}

const GURL& WebContentsImpl::GetLastCommittedURL() const {
  // We may not have a navigation entry yet.
  const NavigationEntry* entry = GetController().GetLastCommittedEntry();
  return entry ? entry->GetVirtualURL() : GURL::EmptyGURL();
}

WebContentsDelegate* WebContentsImpl::GetDelegate() {
  return delegate_;
}

void WebContentsImpl::SetDelegate(WebContentsDelegate* delegate) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::SetDelegate", "delegate",
                        static_cast<void*>(delegate));
  // TODO(cbentzel): remove this debugging code?
  if (delegate == delegate_) {
    return;
  }
  const bool had_delegate = !!delegate_;
  if (had_delegate) {
    delegate_->Detach(this);
  }
  delegate_ = delegate;
  if (delegate_) {
    delegate_->Attach(this);
    // RenderFrameDevToolsAgentHost should not be told about the WebContents
    // until there is a `delegate_`.
    if (!had_delegate) {
      RenderFrameDevToolsAgentHost::AttachToWebContents(this);
    }
  }

  // Re-read values from the new delegate and apply them.
  if (view_) {
    view_->SetOverscrollControllerEnabled(CanOverscrollContent());
  }
}

const RenderFrameHostImpl* WebContentsImpl::GetPrimaryMainFrame() const {
  return primary_frame_tree_.root()->current_frame_host();
}

RenderFrameHostImpl* WebContentsImpl::GetPrimaryMainFrame() {
  return const_cast<RenderFrameHostImpl*>(
      std::as_const(*this).GetPrimaryMainFrame());
}

PageImpl& WebContentsImpl::GetPrimaryPage() {
  // We should not be accessing Page during the destruction of this WebContents,
  // as the Page has already been cleared.
  //
  // Please note that IsBeingDestroyed() should be checked to ensure that we
  // don't access Page related data that is going to be destroyed.
  CHECK(primary_frame_tree_.root()->current_frame_host());
  return primary_frame_tree_.root()->current_frame_host()->GetPage();
}

RenderFrameHostImpl* WebContentsImpl::GetFocusedFrame() {
  // If this method is called on an inner WebContents, don't return frames from
  // outside of the inner WebContents's subtree.
  if (GetOuterWebContents() && !ContainsOrIsFocusedWebContents()) {
    return nullptr;
  }

  FrameTreeNode* focused_node = GetFocusedFrameTree()->GetFocusedFrame();
  if (!focused_node) {
    return nullptr;
  }

  // If an inner frame tree has focus, we should return a RenderFrameHost from
  // the inner frame tree and not the placeholder RenderFrameHost.
  DCHECK(focused_node->current_frame_host()
             ->inner_tree_main_frame_tree_node_id()
             .is_null());

  return focused_node->current_frame_host();
}

bool WebContentsImpl::IsPrerenderedFrame(FrameTreeNodeId frame_tree_node_id) {
  if (frame_tree_node_id.is_null()) {
    return false;
  }

  FrameTreeNode* frame_tree_node =
      FrameTreeNode::GloballyFindByID(frame_tree_node_id);
  if (!frame_tree_node) {
    return false;
  }

  // In the case of inner frame trees in a prerender, the inner frame tree's
  // type, would not be FrameTree::Type::kPrerender. So if this is not the
  // outermost frame, we use the lifecycle state of the document that owns this.
  // TODO(1196715, 1232528): This relies on the LifecycleState being correct
  // in the case of inner frame trees.
  if (frame_tree_node->GetParentOrOuterDocumentOrEmbedder()) {
    return frame_tree_node->GetParentOrOuterDocumentOrEmbedder()
               ->lifecycle_state() ==
           RenderFrameHostImpl::LifecycleStateImpl::kPrerendering;
  }
  return frame_tree_node->GetFrameType() == FrameType::kPrerenderMainFrame;
}

RenderFrameHostImpl* WebContentsImpl::UnsafeFindFrameByFrameTreeNodeId(
    FrameTreeNodeId frame_tree_node_id) {
  OPTIONAL_TRACE_EVENT1("content",
                        "WebContentsImpl::UnsafeFindFrameByFrameTreeNodeId",
                        "frame_tree_node_id", frame_tree_node_id);
  // Beware using this! The RenderFrameHost may have changed since the caller
  // obtained frame_tree_node_id.
  FrameTreeNode* ftn = FrameTreeNode::GloballyFindByID(frame_tree_node_id);
  if (!ftn) {
    return nullptr;
  }
  if (this != WebContents::FromRenderFrameHost(ftn->current_frame_host())) {
    return nullptr;
  }
  return ftn->current_frame_host();
}

void WebContentsImpl::ForEachRenderFrameHostWithAction(
    base::FunctionRef<FrameIterationAction(RenderFrameHost*)> on_frame) {
  ForEachRenderFrameHostImplWithAction(
      [on_frame](RenderFrameHostImpl* rfh) { return on_frame(rfh); });
}

void WebContentsImpl::ForEachRenderFrameHost(
    base::FunctionRef<void(RenderFrameHost*)> on_frame) {
  ForEachRenderFrameHostImpl(
      [on_frame](RenderFrameHostImpl* rfh) { on_frame(rfh); });
}

void WebContentsImpl::ForEachRenderFrameHostImplWithAction(
    base::FunctionRef<FrameIterationAction(RenderFrameHostImpl*)> on_frame) {
  ForEachRenderFrameHostImpl(on_frame, /* include_speculative */ false);
}

void WebContentsImpl::ForEachRenderFrameHostImpl(
    base::FunctionRef<void(RenderFrameHostImpl*)> on_frame) {
  ForEachRenderFrameHostImplWithAction([on_frame](RenderFrameHostImpl* rfh) {
    on_frame(rfh);
    return FrameIterationAction::kContinue;
  });
}

void WebContentsImpl::ForEachRenderFrameHostImplIncludingSpeculativeWithAction(
    base::FunctionRef<FrameIterationAction(RenderFrameHostImpl*)> on_frame) {
  ForEachRenderFrameHostImpl(on_frame, /* include_speculative */ true);
}

void WebContentsImpl::ForEachRenderFrameHostImplIncludingSpeculative(
    base::FunctionRef<void(RenderFrameHostImpl*)> on_frame) {
  ForEachRenderFrameHostImplIncludingSpeculativeWithAction(
      [on_frame](RenderFrameHostImpl* rfh) {
        on_frame(rfh);
        return FrameIterationAction::kContinue;
      });
}

void WebContentsImpl::ForEachRenderFrameHostImpl(
    base::FunctionRef<FrameIterationAction(RenderFrameHostImpl*)> on_frame,
    bool include_speculative) {
  // Since `RenderFrameHostImpl::ForEachRenderFrameHostImpl` will reach the
  // RenderFrameHosts descending from a specified root, it is enough to start
  // iteration from each of the outermost main frames to reach everything in
  // this WebContents. However, if iteration stops early in
  // `RenderFrameHostImpl::ForEachRenderFrameHostImpl`, we also need to stop
  // early by not iterating over additional outermost main frames.
  bool iteration_stopped = false;
  auto on_frame_with_termination =
      [on_frame, &iteration_stopped](RenderFrameHostImpl* rfh) {
        const auto action = on_frame(rfh);
        if (action == FrameIterationAction::kStop) {
          iteration_stopped = true;
        }
        return action;
      };

  for (auto* rfh : GetOutermostMainFrames()) {
    if (include_speculative) {
      rfh->ForEachRenderFrameHostImplIncludingSpeculativeWithAction(
          on_frame_with_termination);
    } else {
      rfh->ForEachRenderFrameHostImplWithAction(on_frame_with_termination);
    }

    if (iteration_stopped) {
      return;
    }
  }
}

void WebContentsImpl::ForEachFrameTree(
    FrameTreeIterationCallback on_frame_tree) {
  // Consider all outermost frame trees, and for each, iterate through their
  // FrameTreeNodes to find any inner frame trees.
  for (FrameTree* outermost_frame_tree : GetOutermostFrameTrees()) {
    FrameTree::NodeRange node_range =
        outermost_frame_tree->NodesIncludingInnerTreeNodes();
    FrameTree::NodeIterator node_iter = node_range.begin();
    while (node_iter != node_range.end()) {
      FrameTreeNode* node = *node_iter;
      if (FromFrameTreeNode(node) != this) {
        // Exclude any inner frame trees based on multi-WebContents
        // architecture.
        node_iter.AdvanceSkippingChildren();
      } else {
        if (node->IsMainFrame()) {
          on_frame_tree(node->frame_tree());
        }
        ++node_iter;
      }
    }
  }
}

std::vector<FrameTree*> WebContentsImpl::GetOutermostFrameTrees() {
  // If the WebContentsImpl is being destroyed, then we should not
  // perform the tree traversal.
  if (IsBeingDestroyed()) {
    return {};
  }

  std::vector<FrameTree*> result;
  result.push_back(&GetPrimaryFrameTree());

  const std::vector<FrameTree*> prerender_frame_trees =
      GetPrerenderHostRegistry()->GetPrerenderFrameTrees();
  result.insert(result.end(), prerender_frame_trees.begin(),
                prerender_frame_trees.end());

  return result;
}

std::vector<RenderFrameHostImpl*> WebContentsImpl::GetOutermostMainFrames() {
  // Do nothing if the WebContents is currently being initialized or destroyed.
  if (!GetPrimaryMainFrame()) {
    return {};
  }

  std::vector<RenderFrameHostImpl*> result;

  for (FrameTree* outermost_frame_tree : GetOutermostFrameTrees()) {
    DCHECK(outermost_frame_tree->GetMainFrame());
    result.push_back(outermost_frame_tree->GetMainFrame());
  }

  for (const auto& entry : GetController().GetBackForwardCache().GetEntries()) {
    result.push_back(entry->render_frame_host());
  }

  // In the case of inner WebContents, we still allow this method to be called,
  // but the semantics of the values being returned are "outermost
  // within this WebContents" as opposed to truly outermost. When this method is
  // called for an inner WebContents in a normal browser, we would not expect
  // any other outermost pages besides the primary page.
  //
  // Note that for an inner WebContents in a WebUIBrowser (detectable here when
  // the AttachUnownedInnerWebContents feature is enabled), `result.size()` may
  // sometimes exceed 1. For example, for WebUIBrowser, when a prerendering code
  // path is triggered, a prerender frame tree is generated, but the path to
  // activate or discard it does not run before this point.
  //
  // TODO(webium): Fix prerendering and bfcache for WebUIBrowser, which are not
  // yet fully enabled.
  DCHECK(
      !GetOuterWebContents() || (result.size() == 1) ||
      base::FeatureList::IsEnabled(features::kAttachUnownedInnerWebContents));

  return result;
}

void WebContentsImpl::ExecutePageBroadcastMethod(
    PageBroadcastMethodCallback callback) {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::ExecutePageBroadcastMethod");
  primary_frame_tree_.root()->render_manager()->ExecutePageBroadcastMethod(
      callback);
}

void WebContentsImpl::ExecutePageBroadcastMethodForAllPages(
    PageBroadcastMethodCallback callback) {
  OPTIONAL_TRACE_EVENT0(
      "content", "WebContentsImpl::ExecutePageBroadcastMethodForAllPages");
  ForEachFrameTree([callback](FrameTree& frame_tree) {
    frame_tree.root()->render_manager()->ExecutePageBroadcastMethod(callback);
  });
}

RenderViewHostImpl* WebContentsImpl::GetRenderViewHost() {
  return GetRenderManager()->current_frame_host()->render_view_host();
}

void WebContentsImpl::CancelActiveAndPendingDialogs() {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::CancelActiveAndPendingDialogs");
  CancelDialogManagerDialogs(/*reset_state=*/false);
  if (browser_plugin_embedder_) {
    browser_plugin_embedder_->CancelGuestDialogs();
  }
}

void WebContentsImpl::ClosePage() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::ClosePage");
  GetPrimaryMainFrame()->ClosePage(
      RenderFrameHostImpl::ClosePageSource::kBrowser);
}

RenderWidgetHostView* WebContentsImpl::GetRenderWidgetHostView() {
  return GetRenderManager()->GetRenderWidgetHostView();
}

RenderWidgetHostView* WebContentsImpl::GetTopLevelRenderWidgetHostView() {
  if (GetOuterWebContents()) {
    return GetOuterWebContents()->GetTopLevelRenderWidgetHostView();
  }
  return GetRenderManager()->GetRenderWidgetHostView();
}

RenderWidgetHost* WebContentsImpl::FindWidgetAtPoint(const gfx::PointF& point) {
  if (GetOuterWebContents()) {
    return GetOuterWebContents()->FindWidgetAtPoint(point);
  }
  gfx::PointF transformed_point;
  input::RenderWidgetHostViewInput* rwhvi =
      GetInputEventRouter()->GetRenderWidgetHostViewInputAtPoint(
          static_cast<RenderWidgetHostViewBase*>(
              GetTopLevelRenderWidgetHostView()),
          point, &transformed_point);

  RenderWidgetHostImpl* widget_host = RenderWidgetHostImpl::From(
      static_cast<RenderWidgetHostViewBase*>(rwhvi)->GetRenderWidgetHost());
  if (!widget_host) {
    return nullptr;
  }
  return widget_host;
}

WebContentsView* WebContentsImpl::GetView() const {
  return view_.get();
}

void WebContentsImpl::OnScreensChange(bool is_multi_screen_changed) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::OnScreensChange",
                        "is_multi_screen_changed", is_multi_screen_changed);
  // Mac display info may originate from a remote process hosting the NSWindow;
  // this local process display::Screen signal should not trigger updates.
  // TODO(crbug.com/40165350): Unify screen info plumbing, caching, etc.
#if !BUILDFLAG(IS_MAC)
  // This updates Screen attributes and fires Screen.change events as needed,
  // propagating to all widgets through the VisualProperties update waterfall.
  // This is triggered by system changes, not renderer IPC, so explicitly check
  // that the RenderWidgetHostView is valid before sending an update.
  if (RenderWidgetHostViewBase* view =
          GetRenderViewHost()->GetWidget()->GetView()) {
    // Only update top-level views, as child frames will have their ScreenInfos
    // updated by the visual property flow.
    if (!view->IsRenderWidgetHostViewChildFrame()) {
      view->UpdateScreenInfo();
    }
  }
#endif  // !BUILDFLAG(IS_MAC)
}

void WebContentsImpl::OnScreenOrientationChange() {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::OnScreenOrientationChange");
  DCHECK(screen_orientation_provider_);
  DidChangeScreenOrientation();
  screen_orientation_provider_->OnOrientationChange();
}

std::optional<SkColor> WebContentsImpl::GetThemeColor() {
  return GetPrimaryPage().theme_color();
}

std::optional<SkColor> WebContentsImpl::GetBackgroundColor() {
  return GetPrimaryPage().background_color();
}

void WebContentsImpl::SetPageBaseBackgroundColor(std::optional<SkColor> color) {
  if (page_base_background_color_ == color) {
    return;
  }
  page_base_background_color_ = color;
  ExecutePageBroadcastMethod([color](RenderViewHostImpl* rvh) {
    // Null `broadcast` can happen before view is created on the renderer
    // side, in which case this color will be sent in CreateView.
    if (auto& broadcast = rvh->GetAssociatedPageBroadcast()) {
      broadcast->SetPageBaseBackgroundColor(color);
    }
  });
}

void WebContentsImpl::SetColorProviderSource(ui::ColorProviderSource* source) {
  ColorProviderSourceObserver::Observe(source);
}

ui::ColorProviderKey::ColorMode WebContentsImpl::GetColorMode() const {
  // A ColorProviderSource should always be set.
  auto* source = GetColorProviderSource();
  CHECK(source);
  return source->GetColorMode();
}

void WebContentsImpl::SetAccessibilityMode(ui::AXMode mode) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::SetAccessibilityMode",
                        "mode", mode.ToString(), "previous_mode",
                        accessibility_mode_.ToString());

  if (unrecoverable_accessibility_error_) {
    DUMP_WILL_BE_CHECK(accessibility_mode_.is_mode_off());
    return;
  }

  if (mode == accessibility_mode_) {
    return;
  }

  // Don't allow accessibility to be enabled for WebContents that are never
  // user-visible, like background pages.
  CHECK(!is_never_composited_);

  accessibility_mode_ = mode;

  // Update state for all frames in this tree and inner trees, including
  // speculative frame hosts and those in the back-forward cache. Take care not
  // to touch frame hosts that belong to another WebContents (e.g., guest views)
  // -- it is the responsibility of other WebContents' to update their own
  // frames. Note that content::BrowserAccessibilityState will propagate mode
  // flag changes that target the whole process (CreateScopedModeForProcess) or
  // a BrowserContext (CreateScopedModeForBrowserContext) to all relevant
  // WebContents, so inner WebContents will automatically receive the same mode
  // flag changes. In cases where mode flag changes apply to a specific
  // WebContents (via CreateScopedModeForWebContents), it is the responsibility
  // of the owner of the ScopedAccessibilityMode to choose whether or not to
  // create scopers for inner WebContents.
  ForEachRenderFrameHostImplIncludingSpeculativeWithAction(
      [this](RenderFrameHostImpl* frame_host) {
        if (WebContentsImpl::FromRenderFrameHostImpl(frame_host) == this) {
          frame_host->UpdateAccessibilityMode();
          return FrameIterationAction::kContinue;
        }
        return FrameIterationAction::kSkipChildren;
      });
}

void WebContentsImpl::DidCapturedSurfaceControl() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  observers_.NotifyObservers(&WebContentsObserver::OnCapturedSurfaceControl);
}

void WebContentsImpl::ResetAccessibility() {
  // Reset accessibility for all frames in this tree and inner trees, including
  // speculative frame hosts and those in the back-forward cache. See comment in
  // `SetAccessibilityMode()` for more details.
  ForEachRenderFrameHostImplIncludingSpeculativeWithAction(
      [this](RenderFrameHostImpl* frame_host) {
        if (WebContentsImpl::FromRenderFrameHostImpl(frame_host) == this) {
          frame_host->AccessibilityReset();
          return FrameIterationAction::kContinue;
        }
        return FrameIterationAction::kSkipChildren;
      });
}

// Helper class used by WebContentsImpl::RequestAXTreeSnapshot.
// Handles the callbacks from parallel snapshot requests to each frame,
// and feeds the results to an AXTreeCombiner, which converts them into a
// single combined accessibility tree.
class AXTreeSnapshotCombiner : public base::RefCounted<AXTreeSnapshotCombiner> {
 public:
  AXTreeSnapshotCombiner(WebContents::AXTreeSnapshotCallback callback,
                         mojom::SnapshotAccessibilityTreeParamsPtr params)
      : callback_(std::move(callback)), params_(std::move(params)) {}

  WebContents::AXTreeSnapshotCallback AddFrame(bool is_root) {
    // Adds a reference to |this|.
    return base::BindOnce(&AXTreeSnapshotCombiner::ReceiveSnapshot, this,
                          is_root);
  }

  void ReceiveSnapshot(bool is_root, ui::AXTreeUpdate& snapshot) {
    combiner_.AddTree(snapshot, is_root);
  }

  void AXTreeSnapshotOnFrame(RenderFrameHostImpl* rfhi) {
    OPTIONAL_TRACE_EVENT0("content",
                          "AXTreeSnapshotCombiner::AXTreeSnapshotOnFrame");
    bool is_root = rfhi->AccessibilityIsRootFrame();
    rfhi->RequestAXTreeSnapshot(AddFrame(is_root), params_.Clone());
  }

 private:
  friend class base::RefCounted<AXTreeSnapshotCombiner>;

  // This is called automatically after the last call to ReceiveSnapshot
  // when there are no more references to this object.
  ~AXTreeSnapshotCombiner() {
    combiner_.Combine();
    CHECK(combiner_.combined());
    ui::AXTreeUpdate update = std::move(combiner_.combined().value());
    std::move(callback_).Run(update);
  }

  ui::AXTreeCombiner combiner_;
  WebContents::AXTreeSnapshotCallback callback_;
  mojom::SnapshotAccessibilityTreeParamsPtr params_;
};

void WebContentsImpl::RequestAXTreeSnapshot(AXTreeSnapshotCallback callback,
                                            ui::AXMode ax_mode,
                                            size_t max_nodes,
                                            base::TimeDelta timeout,
                                            AXTreeSnapshotPolicy policy) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::RequestAXTreeSnapshot",
                        "mode", ax_mode.ToString());

  // Inline text boxes are not supported in snapshots, as they are extra noise
  // and expensive. If they are needed in the future, remove this line.
  ax_mode.set_mode(ui::AXMode::kInlineTextBoxes, false);

  // Send a request to each of the frames in parallel. Each one will return
  // an accessibility tree snapshot, and AXTreeSnapshotCombiner will combine
  // them into a single tree and call |callback| with that result, then
  // delete |combiner|.
  auto params = mojom::SnapshotAccessibilityTreeParams::New();
  params->ax_mode = ax_mode.flags();
  params->max_nodes = max_nodes;
  params->timeout = timeout;

  auto combiner = base::MakeRefCounted<AXTreeSnapshotCombiner>(
      std::move(callback), std::move(params));
  GetPrimaryMainFrame()->ForEachRenderFrameHostImplWithAction(
      [this, &combiner, policy](RenderFrameHostImpl* rfh) {
        switch (policy) {
          case AXTreeSnapshotPolicy::kAll:
            break;
          case AXTreeSnapshotPolicy::kSameOriginDirectDescendants:
            if (GetPrimaryMainFrame()->GetSiteInstance() !=
                    rfh->GetSiteInstance() ||
                rfh->IsFencedFrameRoot() ||
                !GetPrimaryMainFrame()
                     ->GetLastCommittedOrigin()
                     .IsSameOriginWith(rfh->GetLastCommittedOrigin())) {
              return FrameIterationAction::kSkipChildren;
            }
            break;
        }
        combiner->AXTreeSnapshotOnFrame(rfh);
        return FrameIterationAction::kContinue;
      });
}

void WebContentsImpl::NotifyViewportFitChanged(
    blink::mojom::ViewportFit value) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::NotifyViewportFitChanged",
                        "value", static_cast<int>(value));
  observers_.NotifyObservers(&WebContentsObserver::ViewportFitChanged, value);
}

void WebContentsImpl::NotifySafeAreaConstraintChanged(bool has_constraint) {
  OPTIONAL_TRACE_EVENT1("content",
                        "WebContentsImpl::NotifySafeAreaConstraintChanged",
                        "has_constraint", has_constraint);
  observers_.NotifyObservers(&WebContentsObserver::SafeAreaConstraintChanged,
                             has_constraint);
}

FindRequestManager* WebContentsImpl::GetFindRequestManagerForTesting() {
  return GetOrCreateFindRequestManager();
}

void WebContentsImpl::UpdateZoom() {
  UpdateZoom(GetPrimaryMainFrame()->GetGlobalId());
}

void WebContentsImpl::UpdateZoom(const GlobalRenderFrameHostId& rfh_id) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::UpdateZoom");
  RenderFrameHostImpl* rfh = RenderFrameHostImpl::FromID(rfh_id);
  RenderWidgetHostImpl* rwh = rfh->GetRenderWidgetHost();
  if (rwh->GetView()) {
    rwh->SynchronizeVisualProperties();
  }
}

void WebContentsImpl::UpdateZoomIfNecessary(const std::string& scheme,
                                            const std::string& host) {
  UpdateZoomIfNecessary(scheme, host, GetPrimaryMainFrame());
}

void WebContentsImpl::UpdateZoomIfNecessary(const std::string& scheme,
                                            const std::string& host,
                                            RenderFrameHostImpl* rfh) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::UpdateZoomIfNecessary",
                        "scheme", scheme, "host", host);

  // The following code expects that rfh has its own independent zoom.
  GURL url = HostZoomMap::GetURLForRenderFrameHost(rfh->GetGlobalId());
  if (host != net::GetHostOrSpecFromURL(url) ||
      (!scheme.empty() && !url.SchemeIs(scheme))) {
    return;
  }

  UpdateZoom(rfh->GetGlobalId());
}

std::vector<WebContentsImpl*> WebContentsImpl::GetWebContentsAndAllInner() {
  std::vector<WebContentsImpl*> all_contents(1, this);

  for (size_t i = 0; i != all_contents.size(); ++i) {
    for (auto* inner_contents : all_contents[i]->GetInnerWebContents()) {
      all_contents.push_back(static_cast<WebContentsImpl*>(inner_contents));
    }
  }

  return all_contents;
}

void WebContentsImpl::OnManifestUrlChanged(PageImpl& page) {
  std::optional<GURL> manifest_url = page.GetManifestUrl();
  if (!manifest_url.has_value()) {
    return;
  }

  if (!page.IsPrimary()) {
    return;
  }

  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::NotifyManifestUrlChanged",
                        "render_frame_host", &page.GetMainDocument(),
                        "manifest_url", manifest_url);
  observers_.NotifyObservers(&WebContentsObserver::DidUpdateWebManifestURL,
                             &page.GetMainDocument(), *manifest_url);
}

WebUI* WebContentsImpl::GetWebUI() {
  // There is no frame host if the navigation fails.
  if (!primary_frame_tree_.root()->current_frame_host()) {
    return nullptr;
  }

  return primary_frame_tree_.root()->current_frame_host()->web_ui();
}

void WebContentsImpl::SetAlwaysSendSubresourceNotifications() {
  if (!base::FeatureList::IsEnabled(
          features::kReduceSubresourceResponseStartedIPC)) {
    return;
  }

  if (GetSendSubresourceNotification()) {
    return;
  }

  // Updates all the renderers if the user allows certificate error or HTTP
  // exception, but doesn't update renderers when all exceptions are revoked
  // from all hosts since this causes superfluous IPCs.
  for (WebContentsImpl* web_contents : GetAllWebContents()) {
    DCHECK(!web_contents->GetSendSubresourceNotification());
    web_contents->renderer_preferences_.send_subresource_notification = true;
    web_contents->SyncRendererPrefs();
  }
}

bool WebContentsImpl::GetSendSubresourceNotification() {
  return GetRendererPrefs(GetRenderViewHost()).send_subresource_notification;
}

void WebContentsImpl::SetUserAgentOverride(
    const blink::UserAgentOverride& ua_override,
    bool override_in_new_tabs) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::SetUserAgentOverride",
                        "ua_override", ua_override.ua_string_override,
                        "override_in_new_tabs", override_in_new_tabs);
  DCHECK(!ua_override.ua_metadata_override.has_value() ||
         !ua_override.ua_string_override.empty());

  if (GetUserAgentOverride() == ua_override) {
    return;
  }

  if (!ua_override.ua_string_override.empty() &&
      !net::HttpUtil::IsValidHeaderValue(ua_override.ua_string_override)) {
    return;
  }

  should_override_user_agent_in_new_tabs_ = override_in_new_tabs;

  // Update any in-flight load requests with overrides for new tabs.
  if (delayed_load_url_params_.get()) {
    delayed_load_url_params_->override_user_agent =
        override_in_new_tabs ? NavigationController::UA_OVERRIDE_TRUE
                             : NavigationController::UA_OVERRIDE_FALSE;
  }

  renderer_preferences_.user_agent_override = ua_override;

  // Send the new override string to all renderers in the current page.
  SyncRendererPrefs();

  // Reload the page if a load is currently in progress to avoid having
  // different parts of the page loaded using different user agents.
  // No need to reload if the current entry matches that of the
  // NavigationRequest supplied to DidStartNavigation() as NavigationRequest
  // handles it.
  ForEachFrameTree([](FrameTree& frame_tree) {
    // For prerendering, we don't want to activate a prerendered page loaded
    // with a stale UA and will handle it even if it finishes loading.
    if (!frame_tree.IsLoadingIncludingInnerFrameTrees() &&
        !frame_tree.is_prerendering()) {
      return;
    }

    NavigationEntry* entry = frame_tree.controller().GetVisibleEntry();
    if (!entry || !entry->GetIsOverridingUserAgent()) {
      return;
    }
    if (frame_tree.root()->navigation_request() &&
        !frame_tree.root()->navigation_request()->ua_change_requires_reload()) {
      return;
    }
    if (frame_tree.is_prerendering()) {
      // Just cancel if the FrameTree is for prerendering, as prerendered
      // page may not allow another navigation including a reload, depending
      // on conditions.
      frame_tree.GetMainFrame()->CancelPrerendering(PrerenderCancellationReason(
          PrerenderFinalStatus::kUaChangeRequiresReload));
    } else {
      frame_tree.controller().Reload(ReloadType::BYPASSING_CACHE, true);
    }
  });

  observers_.NotifyObservers(&WebContentsObserver::UserAgentOverrideSet,
                             ua_override);
}

const blink::UserAgentOverride& WebContentsImpl::GetUserAgentOverride() {
  return renderer_preferences_.user_agent_override;
}

const blink::UserAgentOverride& WebContentsImpl::GetUserAgentOverride(
    FrameTree& frame_tree) {
  if (auto* guest = GuestPageHolderImpl::FromRenderFrameHost(
          *frame_tree.GetMainFrame())) {
    return guest->GetRendererPrefs().user_agent_override;
  }
  return renderer_preferences_.user_agent_override;
}

bool WebContentsImpl::ShouldOverrideUserAgentForRendererInitiatedNavigation() {
  // Inherits the current entry setting if it exists and not initial.
  NavigationEntryImpl* current_entry = GetController().GetLastCommittedEntry();
  if (current_entry && !current_entry->IsInitialEntry()) {
    return current_entry->GetIsOverridingUserAgent();
  }
  // Otherwise, follows the setting from the last user-agent override. See
  // `override_in_new_tabs` in `SetUserAgentOverride()`.
  return should_override_user_agent_in_new_tabs_;
}

bool WebContentsImpl::IsWebContentsOnlyAccessibilityModeForTesting() {
  return accessibility_mode_ == ui::kAXModeWebContentsOnly;
}

bool WebContentsImpl::IsFullAccessibilityModeForTesting() {
  return accessibility_mode_ == ui::kAXModeDefaultForTests;
}

#if BUILDFLAG(IS_ANDROID)

void WebContentsImpl::SetDisplayCutoutSafeArea(gfx::Insets insets) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::SetDisplayCutoutSafeArea");
  if (safe_area_insets_host_) {
    safe_area_insets_host_->SetDisplayCutoutSafeArea(insets);
  }
}

void WebContentsImpl::ShowInterestInElement(int nodeID) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::ShowInterestInElement");
  if (auto* rwhv = GetRenderWidgetHostView()) {
    rwhv->ShowInterestInElement(nodeID);
  }
}

#endif

const std::u16string& WebContentsImpl::GetTitle() {
  WebUI* our_web_ui =
      GetRenderManager()->speculative_frame_host()
          ? GetRenderManager()->speculative_frame_host()->web_ui()
          : GetRenderManager()->current_frame_host()->web_ui();
  if (our_web_ui) {
    // Don't override the title in view source mode.
    NavigationEntry* entry = GetController().GetVisibleEntry();
    if (!(entry && entry->IsViewSourceMode())) {
      // Give the Web UI the chance to override our title.
      const std::u16string& title = our_web_ui->GetOverriddenTitle();
      if (!title.empty()) {
        return title;
      }
    }
  }

  return GetNavigationEntryForTitle()->GetTitleForDisplay();
}

const std::optional<std::u16string>& WebContentsImpl::GetApplicationTitle() {
  return GetNavigationEntryForTitle()->GetApplicationTitle();
}

SiteInstanceImpl* WebContentsImpl::GetSiteInstance() {
  return GetRenderManager()->current_frame_host()->GetSiteInstance();
}

bool WebContentsImpl::IsLoading() {
  return primary_frame_tree_.IsLoadingIncludingInnerFrameTrees();
}

double WebContentsImpl::GetLoadProgress() {
  // TODO(crbug.com/40177943): Make this MPArch friendly considering primary
  // frame tree and its descendants.
  return primary_frame_tree_.GetLoadProgress();
}

bool WebContentsImpl::ShouldShowLoadingUI() {
  return primary_frame_tree_.GetLoadingState() ==
         LoadingState::LOADING_UI_REQUESTED;
}

bool WebContentsImpl::IsDocumentOnLoadCompletedInPrimaryMainFrame() {
  // TODO(mparch): This should be moved to Page, and callers should use it
  // directly.
  return GetPrimaryPage().is_on_load_completed_in_main_document();
}

bool WebContentsImpl::IsWaitingForResponse() {
  NavigationRequest* ongoing_navigation_request =
      primary_frame_tree_.root()->navigation_request();

  // An ongoing navigation request means we're waiting for a response.
  return ongoing_navigation_request != nullptr;
}

bool WebContentsImpl::HasUncommittedNavigationInPrimaryMainFrame() {
  return primary_frame_tree_.root()->HasNavigation();
}

const net::LoadStateWithParam& WebContentsImpl::GetLoadState() {
  return load_state_;
}

const std::u16string& WebContentsImpl::GetLoadStateHost() {
  return load_state_host_;
}

uint64_t WebContentsImpl::GetUploadSize() {
  return upload_size_;
}

uint64_t WebContentsImpl::GetUploadPosition() {
  return upload_position_;
}

const std::string& WebContentsImpl::GetEncoding() {
  return GetPrimaryPage().GetEncoding();
}

void WebContentsImpl::Discard(base::OnceClosure on_discarded_cb) {
  if (!base::FeatureList::IsEnabled(features::kWebContentsDiscard)) {
    NOTREACHED();
  }
  if (WasDiscarded()) {
    // TODO(crbug.com/441841249): Consider updating `on_discarded_cb` to return
    // a bool to indicate whether the operation completed successfully.
    return;
  }

  AboutToBeDiscarded(this);
  notify_disconnection_ = false;
  CancelAllPrerendering();
  primary_frame_tree_.Discard(std::move(on_discarded_cb));
  NotifyWasDiscarded();
}

bool WebContentsImpl::WasDiscarded() {
  return GetPrimaryFrameTree().root()->was_discarded();
}

void WebContentsImpl::SetWasDiscarded(bool was_discarded) {
  // It's set based on a tab and the setting value is started from a primary
  // tree and propagated to all children nodes including a fenced frame node.
  GetPrimaryFrameTree().root()->set_was_discarded();
}

base::ScopedClosureRunner WebContentsImpl::IncrementCapturerCount(
    const gfx::Size& capture_size,
    bool stay_hidden,
    bool stay_awake,
    bool is_activity) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::IncrementCapturerCount");
  DCHECK(!IsBeingDestroyed());
  if (stay_hidden) {
    // A hidden capture should not have side effect on the web contents, so it
    // should not pass a non-empty |capture_size| which will cause side effect.
    DCHECK(capture_size.IsEmpty());
    ++hidden_capturer_count_;
  } else {
    ++visible_capturer_count_;
  }

  if (stay_awake) {
    ++stay_awake_capturer_count_;
  }

  view_->OnCapturerCountChanged();

  // Note: This provides a hint to upstream code to size the views optimally
  // for quality (e.g., to avoid scaling).
  if (!capture_size.IsEmpty() && preferred_size_for_capture_.IsEmpty()) {
    preferred_size_for_capture_ = capture_size;
    OnPreferredSizeChanged(preferred_size_);
  }

  if (!capture_wake_lock_ && stay_awake_capturer_count_) {
    if (auto* wake_lock_context = GetWakeLockContext()) {
      auto receiver = capture_wake_lock_.BindNewPipeAndPassReceiver();
      wake_lock_context->GetWakeLock(
          device::mojom::WakeLockType::kPreventDisplaySleepAllowDimming,
          device::mojom::WakeLockReason::kOther, "Capturing",
          std::move(receiver));
    }
  }

  if (capture_wake_lock_) {
    capture_wake_lock_->RequestWakeLock();
  }

  UpdateVisibilityAndNotifyPageAndView(GetVisibility(), is_activity);

  return base::ScopedClosureRunner(base::BindOnce(
      &WebContentsImpl::DecrementCapturerCount, weak_factory_.GetWeakPtr(),
      stay_hidden, stay_awake, is_activity));
}

const blink::mojom::CaptureHandleConfig&
WebContentsImpl::GetCaptureHandleConfig() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  return capture_handle_config_;
}

bool WebContentsImpl::IsBeingCaptured() {
  return visible_capturer_count_ + hidden_capturer_count_ > 0;
}

bool WebContentsImpl::IsBeingVisiblyCaptured() {
  return visible_capturer_count_ > 0;
}

bool WebContentsImpl::IsAudioMuted() {
  return audio_stream_factory_ && audio_stream_factory_->IsMuted();
}

void WebContentsImpl::SetAudioMuted(bool mute) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::SetAudioMuted", "mute",
                        mute);
  DVLOG(1) << "SetAudioMuted(mute=" << mute << "), was " << IsAudioMuted()
           << " for WebContentsImpl@" << this;

  if (mute == IsAudioMuted()) {
    return;
  }

  GetAudioStreamFactory()->SetMuted(mute);

  // Notfiy all guest page holders that we are muting.
  ForEachFrameTree([mute](FrameTree& frame_tree) {
    if (frame_tree.is_guest()) {
      GuestPageHolderImpl* guest_page_holder =
          GuestPageHolderImpl::FromRenderFrameHost(
              *frame_tree.root()->current_frame_host());
      CHECK(guest_page_holder);
      guest_page_holder->SetAudioMutedFromWebContents(mute);
    }
  });

  observers_.NotifyObservers(&WebContentsObserver::DidUpdateAudioMutingState,
                             mute);
  // Notification for UI updates in response to the changed muting state.
  NotifyNavigationStateChanged(INVALIDATE_TYPE_AUDIO);
}

bool WebContentsImpl::IsCurrentlyAudible() {
  return is_currently_audible_;
}

bool WebContentsImpl::IsCapabilityActive(
    WebContentsCapabilityType capability_type) {
  switch (capability_type) {
    case WebContentsCapabilityType::kBluetoothConnected:
      return bluetooth_connected_device_count_ > 0;
    case WebContentsCapabilityType::kBluetoothScanning:
      return bluetooth_scanning_sessions_count_ > 0;
    case WebContentsCapabilityType::kSerial:
      return serial_active_frame_count_ > 0;
    case WebContentsCapabilityType::kHID:
      return hid_active_frame_count_ > 0;
    case WebContentsCapabilityType::kUSB:
      return usb_active_frame_count_ > 0;
    case WebContentsCapabilityType::kGeolocation:
      return geolocation_active_frame_count_ > 0;
  }
}

bool WebContentsImpl::HasFileSystemAccessHandles() {
  return file_system_access_handle_count_ > 0;
}

bool WebContentsImpl::HasPictureInPictureVideo() {
  return has_picture_in_picture_video_;
}

bool WebContentsImpl::HasPictureInPictureDocument() {
  return has_picture_in_picture_document_;
}

void WebContentsImpl::SetHasPictureInPictureCommon(
    bool has_picture_in_picture) {
  NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
  observers_.NotifyObservers(&WebContentsObserver::MediaPictureInPictureChanged,
                             has_picture_in_picture);

  // Picture-in-picture state can affect how we notify visibility for non-
  // visible pages.
  if (visibility_ != Visibility::VISIBLE) {
    UpdateVisibilityAndNotifyPageAndView(visibility_);
  }
}

void WebContentsImpl::DisallowCustomCursorScopeExpired() {
  --disallow_custom_cursor_scope_count_;
}

void WebContentsImpl::SetHasPictureInPictureVideo(
    bool has_picture_in_picture_video) {
  OPTIONAL_TRACE_EVENT1("content",
                        "WebContentsImpl::SetHasPictureInPictureVideo",
                        "has_pip_video", has_picture_in_picture_video);
  // If status of |this| is already accurate, there is no need to update.
  if (has_picture_in_picture_video == has_picture_in_picture_video_) {
    return;
  }
  has_picture_in_picture_video_ = has_picture_in_picture_video;
  SetHasPictureInPictureCommon(has_picture_in_picture_video);
}

void WebContentsImpl::SetHasPictureInPictureDocument(
    bool has_picture_in_picture_document) {
  OPTIONAL_TRACE_EVENT1("content",
                        "WebContentsImpl::SetHasPictureInPictureDocument",
                        "has_pip_document", has_picture_in_picture_document);
  // If status of |this| is already accurate, there is no need to update.
  if (has_picture_in_picture_document == has_picture_in_picture_document_) {
    return;
  }
  has_picture_in_picture_document_ = has_picture_in_picture_document;
  SetHasPictureInPictureCommon(has_picture_in_picture_document);
}

bool WebContentsImpl::IsCrashed() {
  switch (primary_main_frame_process_status_) {
    case base::TERMINATION_STATUS_PROCESS_CRASHED:
    case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
    case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
    case base::TERMINATION_STATUS_OOM:
    case base::TERMINATION_STATUS_EVICTED_FOR_MEMORY:
    case base::TERMINATION_STATUS_LAUNCH_FAILED:
#if BUILDFLAG(IS_CHROMEOS)
    case base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM:
#endif
#if BUILDFLAG(IS_ANDROID)
    case base::TERMINATION_STATUS_OOM_PROTECTED:
#endif
#if BUILDFLAG(IS_WIN)
    case base::TERMINATION_STATUS_INTEGRITY_FAILURE:
#endif
      return true;
    case base::TERMINATION_STATUS_NORMAL_TERMINATION:
    case base::TERMINATION_STATUS_STILL_RUNNING:
      return false;
    case base::TERMINATION_STATUS_MAX_ENUM:
      NOTREACHED();
  }

  NOTREACHED();
}

void WebContentsImpl::SetPrimaryMainFrameProcessStatus(
    base::TerminationStatus status,
    int error_code) {
  OPTIONAL_TRACE_EVENT2("content",
                        "WebContentsImpl::SetPrimaryMainFrameProcessStatus",
                        "status", static_cast<int>(status), "old_status",
                        static_cast<int>(primary_main_frame_process_status_));
  if (status == primary_main_frame_process_status_) {
    return;
  }

  primary_main_frame_process_status_ = status;
  primary_main_frame_process_error_code_ = error_code;
  NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
}

base::TerminationStatus WebContentsImpl::GetCrashedStatus() {
  return primary_main_frame_process_status_;
}

int WebContentsImpl::GetCrashedErrorCode() {
  return primary_main_frame_process_error_code_;
}

bool WebContentsImpl::IsBeingDestroyed() {
  return is_being_destroyed_;
}

void WebContentsImpl::NotifyNavigationStateChanged(
    InvalidateTypes changed_flags) {
  TRACE_EVENT1("content,navigation",
               "WebContentsImpl::NotifyNavigationStateChanged", "changed_flags",
               static_cast<int>(changed_flags));
  // Notify the media observer of potential audibility changes.
  if (changed_flags & INVALIDATE_TYPE_AUDIO) {
    media_web_contents_observer_->MaybeUpdateAudibleState();
  }

  if (delegate_) {
    delegate_->NavigationStateChanged(this, changed_flags);
  }

  if (GetOuterWebContents()) {
    GetOuterWebContents()->NotifyNavigationStateChanged(changed_flags);
  }
}

void WebContentsImpl::OnVerticalScrollDirectionChanged(
    viz::VerticalScrollDirection scroll_direction) {
  OPTIONAL_TRACE_EVENT1("content",
                        "WebContentsImpl::OnVerticalScrollDirectionChanged",
                        "scroll_direction", static_cast<int>(scroll_direction));
  observers_.NotifyObservers(
      &WebContentsObserver::DidChangeVerticalScrollDirection, scroll_direction);
}

int WebContentsImpl::GetVirtualKeyboardResizeHeight() {
  // Only consider a web contents to be insetted by the virtual keyboard if it
  // is in the currently active tab.
  if (GetVisibility() != Visibility::VISIBLE) {
    return 0;
  }

  // The only mode where the virtual keyboard causes the web contents to be
  // resized is kResizesContent.
  if (GetPrimaryPage().virtual_keyboard_mode() !=
      ui::mojom::VirtualKeyboardMode::kResizesContent) {
    return 0;
  }

  // The virtual keyboard never resizes content when fullscreened.
  if (IsFullscreen()) {
    return 0;
  }

  return GetDelegate() ? GetDelegate()->GetVirtualKeyboardHeight(this) : 0;
}

bool WebContentsImpl::ShouldDoLearning() {
  return !GetBrowserContext()->IsOffTheRecord();
}

void WebContentsImpl::OnAudioStateChanged() {
  // This notification can come from any embedded contents or from this
  // WebContents' stream monitor. Aggregate these signals to get the actual
  // state.
  //
  // Note that guests may not be attached as inner contents, and so may need to
  // be checked separately.  This intentionally does not do a recursive search,
  // since the state is aggregated in each inner WebContents and reflects that
  // whole subtree.
  bool is_currently_audible =
      audio_stream_monitor_.IsCurrentlyAudible() ||
      (browser_plugin_embedder_ &&
       browser_plugin_embedder_->AreAnyGuestsCurrentlyAudible()) ||
      std::ranges::any_of(GetInnerWebContents(),
                          [](WebContents* inner_contents) {
                            return inner_contents->IsCurrentlyAudible();
                          });
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::OnAudioStateChanged",
                        "is_currently_audible", is_currently_audible,
                        "was_audible", is_currently_audible_);
  if (is_currently_audible == is_currently_audible_) {
    return;
  }

  // Update internal state.
  is_currently_audible_ = is_currently_audible;
  was_ever_audible_ = was_ever_audible_ || is_currently_audible_;

  ExecutePageBroadcastMethod([is_currently_audible](RenderViewHostImpl* rvh) {
    if (auto& broadcast = rvh->GetAssociatedPageBroadcast()) {
      broadcast->AudioStateChanged(is_currently_audible);
    }
  });

  // Notification for UI updates in response to the changed audio state.
  NotifyNavigationStateChanged(INVALIDATE_TYPE_AUDIO);

  // Ensure that audio state changes propagate from innermost to outermost
  // WebContents.
  if (GetOuterWebContents()) {
    GetOuterWebContents()->OnAudioStateChanged();
  }

  observers_.NotifyObservers(&WebContentsObserver::OnAudioStateChanged,
                             is_currently_audible_);
}

base::TimeTicks WebContentsImpl::GetLastActiveTimeTicks() {
  return last_active_time_ticks_;
}

base::Time WebContentsImpl::GetLastActiveTime() {
  return last_active_time_;
}

void WebContentsImpl::WasShown() {
  TRACE_EVENT0("content", "WebContentsImpl::WasShown");
  UpdateVisibilityAndNotifyPageAndView(Visibility::VISIBLE);
}

void WebContentsImpl::WasHidden() {
  TRACE_EVENT0("content", "WebContentsImpl::WasHidden");
  UpdateVisibilityAndNotifyPageAndView(Visibility::HIDDEN);
}

bool WebContentsImpl::HasRecentInteraction() {
  if (last_interaction_time_.is_null()) {
    return false;
  }

  static constexpr base::TimeDelta kMaxInterval = base::Seconds(5);
  base::TimeDelta delta = ui::EventTimeForNow() - last_interaction_time_;
  // Note: the expectation is that the caller is typically expecting an input
  // event, e.g. validating that a WebUI message that requires a gesture is
  // actually attached to a gesture.
  return delta <= kMaxInterval;
}

base::TimeTicks WebContentsImpl::GetLastInteractionTimeTicks() {
  return last_interaction_time_;
}

WebContents::ScopedIgnoreInputEvents WebContentsImpl::IgnoreInputEvents(
    std::optional<WebInputEventAuditCallback> audit_callback,
    bool should_ignore_a11y_input) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::IgnoreInputEvents");

  uint64_t callback_id = 0;
  if (audit_callback.has_value()) {
    do {
      callback_id = next_web_input_event_audit_callback_id_++;
    } while (web_input_event_audit_callbacks_.contains(callback_id));
    web_input_event_audit_callbacks_[callback_id] = std::move(*audit_callback);
  } else {
#if BUILDFLAG(IS_ANDROID)
    if (ignore_input_events_count_ == 0) {
      // Reset gesture detection before starting input suppression so that any
      // ongoing scroll gesture is correctly finished.
      //
      // TODO(crbug.com/362301376): This might be a side-effect of the
      // referenced bug. Revisit restoring the CHECK when it's resolved.
      if (auto* view = GetRenderWidgetHostView()) {
        static_cast<RenderWidgetHostViewBase*>(view)->ResetGestureDetection();
      }
    }
#endif
    ++ignore_input_events_count_;
    if (should_ignore_a11y_input) {
      ++ignore_a11y_input_count_;
    }
  }

  // Bind weakly, since the token might outlive us.
  return ScopedIgnoreInputEvents(base::BindOnce(
      [](base::WeakPtr<WebContentsImpl> wc, bool should_ignore_a11y_input,
         std::optional<uint64_t> callback_id) {
        if (wc) {
          OPTIONAL_TRACE_EVENT0("content",
                                "WebContentsImpl::IgnoreInputEvents.Release");
          if (callback_id.has_value()) {
            auto it = wc->web_input_event_audit_callbacks_.find(*callback_id);
            CHECK(it != wc->web_input_event_audit_callbacks_.end());
            wc->web_input_event_audit_callbacks_.erase(it);
          } else {
#if BUILDFLAG(IS_ANDROID)
            // Reset gesture detection so that we don't continue to generate new
            // gestures from suppressed touches. These suppressed gestures would
            // otherwise confuse the event stream validator when input is
            // re-enabled.
            //
            // This needs to be done while input is still suppressed since
            // resetting can generate gesture end events for a gesture sequence
            // which was being suppressed.
            if (wc->ignore_input_events_count_ == 1) {
              if (auto* view = wc->GetRenderWidgetHostView()) {
                static_cast<RenderWidgetHostViewBase*>(view)
                    ->ResetGestureDetection();
              }
            }
#endif
            --wc->ignore_input_events_count_;
            if (should_ignore_a11y_input) {
              --wc->ignore_a11y_input_count_;
            }
          }
        }
      },
      weak_factory_.GetWeakPtr(), should_ignore_a11y_input,
      audit_callback.has_value() ? std::make_optional<uint64_t>(callback_id)
                                 : std::nullopt));
}

bool WebContentsImpl::ShouldIgnoreInputEventsForTesting() {
  return ShouldIgnoreInputEvents();
}

bool WebContentsImpl::ShouldIgnoreA11yInputEventsForTesting() {
  return ShouldIgnoreA11yInputEvents();
}

bool WebContentsImpl::HasActiveEffectivelyFullscreenVideo() {
  return IsFullscreen() &&
         media_web_contents_observer_->HasActiveEffectivelyFullscreenVideo();
}

void WebContentsImpl::WriteIntoTrace(perfetto::TracedValue context) {
  auto dict = std::move(context).WriteDictionary();
  dict.Add("root_frame_tree_node_id",
           primary_frame_tree_.root()->frame_tree_node_id());
}

const base::Location& WebContentsImpl::GetCreatorLocation() {
  return creator_location_;
}

const std::optional<blink::mojom::PictureInPictureWindowOptions>&
WebContentsImpl::GetPictureInPictureOptions() const {
  return picture_in_picture_options_;
}

#if BUILDFLAG(IS_ANDROID)
ChildProcessImportance
WebContentsImpl::GetPrimaryMainFrameImportanceForTesting() {
  return GetPrimaryMainFrame()->GetRenderWidgetHost()->importance();
}

ChildProcessImportance
WebContentsImpl::GetPrimaryPageSubframeImportanceForTesting() {
  return primary_subframe_importance_;
}

void WebContentsImpl::SetPrimaryPageImportance(
    ChildProcessImportance main_frame_importance,
    ChildProcessImportance subframe_importance) {
  OPTIONAL_TRACE_EVENT2(
      "content", "WebContentsImpl::SetPrimaryPageImportance",
      "main_frame_importance", static_cast<int>(main_frame_importance),
      "subframe_importance", static_cast<int>(subframe_importance));
  CHECK(IsPerceptibleImportanceSupported() ||
        (main_frame_importance != ChildProcessImportance::PERCEPTIBLE &&
         subframe_importance != ChildProcessImportance::PERCEPTIBLE))
      << "Setter of ChildProcessImportance::PERCEPTIBLE should be aware of the "
         "support and avoid using PERCEPTIBLE if "
         "IsPerceptibleImportanceSupported() is false";
  CHECK(main_frame_importance >= subframe_importance);

  if (base::FeatureList::IsEnabled(features::kSubframeImportance)) {
    CHECK(
        base::FeatureList::IsEnabled(features::kSubframePriorityContribution));
    if (subframe_importance != primary_subframe_importance_) {
      primary_subframe_importance_ = subframe_importance;
      ApplyPrimaryPageSubframeImportance();
    }
  }

  GetPrimaryMainFrame()->GetRenderWidgetHost()->SetImportance(
      main_frame_importance);
}

void WebContentsImpl::ApplyPrimaryPageSubframeImportance() {
  OPTIONAL_TRACE_EVENT1(
      "content", "WebContentsImpl::ApplyPrimaryPageSubframeImportance",
      "importance", static_cast<int>(primary_subframe_importance_));
  for (FrameTreeNode* node : primary_frame_tree_.Nodes()) {
    if (node->IsMainFrame()) {
      continue;
    }
    if (auto* rwh = node->current_frame_host()->GetLocalRenderWidgetHost()) {
      rwh->SetImportance(primary_subframe_importance_);
    }
  }
}
#endif

void WebContentsImpl::WasOccluded() {
  TRACE_EVENT0("content", "WebContentsImpl::WasOccluded");
  UpdateVisibilityAndNotifyPageAndView(Visibility::OCCLUDED);
}

Visibility WebContentsImpl::GetVisibility() {
  return visibility_;
}

bool WebContentsImpl::NeedToFireBeforeUnloadOrUnloadEvents() {
  if (!notify_disconnection_) {
    return false;
  }

  // Don't fire if the main frame indicates that beforeunload and unload have
  // already executed (e.g., after receiving a ClosePage ACK) or should be
  // ignored.
  if (GetPrimaryMainFrame()->IsPageReadyToBeClosed()) {
    return false;
  }

  // Check whether any frame in the frame tree needs to run beforeunload or
  // unload-time event handlers.
  for (FrameTreeNode* node : primary_frame_tree_.Nodes()) {
    RenderFrameHostImpl* rfh = node->current_frame_host();

    // No need to run beforeunload/unload-time events if the RenderFrame isn't
    // live.
    if (!rfh->IsRenderFrameLive()) {
      continue;
    }
    bool should_run_before_unload_handler =
        rfh->GetSuddenTerminationDisablerState(
            blink::mojom::SuddenTerminationDisablerType::kBeforeUnloadHandler);
    bool should_run_unload_handler = rfh->GetSuddenTerminationDisablerState(
        blink::mojom::SuddenTerminationDisablerType::kUnloadHandler);
    bool should_run_page_hide_handler = rfh->GetSuddenTerminationDisablerState(
        blink::mojom::SuddenTerminationDisablerType::kPageHideHandler);
    auto* rvh = static_cast<RenderViewHostImpl*>(rfh->GetRenderViewHost());
    // If the tab is already hidden, we should not run visibilitychange
    // handlers.
    bool is_page_visible = rvh->GetPageLifecycleStateManager()
                               ->CalculatePageLifecycleState()
                               ->visibility == PageVisibilityState::kVisible;

    bool should_run_visibility_change_handler =
        is_page_visible && rfh->GetSuddenTerminationDisablerState(
                               blink::mojom::SuddenTerminationDisablerType::
                                   kVisibilityChangeHandler);
    if (should_run_before_unload_handler || should_run_unload_handler ||
        should_run_page_hide_handler || should_run_visibility_change_handler) {
      return true;
    }
  }

  return false;
}

void WebContentsImpl::DispatchBeforeUnload(bool auto_cancel) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::DispatchBeforeUnload",
                        "auto_cancel", auto_cancel);
  auto before_unload_type =
      auto_cancel ? RenderFrameHostImpl::BeforeUnloadType::DISCARD
                  : RenderFrameHostImpl::BeforeUnloadType::TAB_CLOSE;
  GetPrimaryMainFrame()->DispatchBeforeUnload(before_unload_type, false);
}

bool WebContentsImpl::IsInnerWebContentsForGuest() {
  return IsGuest();
}

void WebContentsImpl::AttachInnerWebContents(
    std::unique_ptr<WebContents> inner_web_contents,
    RenderFrameHost* render_frame_host,
    bool is_full_page) {
  // Not reachable with MPArch based guest view.
  CHECK(!base::FeatureList::IsEnabled(features::kGuestViewMPArch));
  AttachInnerWebContentsImpl(inner_web_contents.release(), render_frame_host,
                             is_full_page,
                             /*should_take_ownership=*/true);
}

void WebContentsImpl::AttachUnownedInnerWebContents(
    base::PassKey<UnownedInnerWebContentsClient>,
    WebContents* inner_web_contents,
    RenderFrameHost* render_frame_host) {
  AttachInnerWebContentsImpl(inner_web_contents, render_frame_host,
                             /*is_full_page=*/false,
                             /*should_take_ownership=*/false);
}

void WebContentsImpl::AttachInnerWebContentsImpl(
    WebContents* inner_web_contents,
    RenderFrameHost* render_frame_host,
    bool is_full_page,
    bool should_take_ownership) {
  OPTIONAL_TRACE_EVENT("content", "WebContentsImpl::AttachInnerWebContents",
                       "inner_web_contents",
                       static_cast<void*>(inner_web_contents), "is_full_page",
                       is_full_page, "should_take_ownership",
                       should_take_ownership);
  WebContentsImpl* inner_web_contents_impl =
      static_cast<WebContentsImpl*>(inner_web_contents);
  DCHECK(!inner_web_contents_impl->node_.outer_web_contents());
  auto* render_frame_host_impl =
      static_cast<RenderFrameHostImpl*>(render_frame_host);
  DCHECK_EQ(this, WebContents::FromRenderFrameHost(render_frame_host_impl));
  DCHECK(render_frame_host_impl->GetParent());

  // Inner WebContents aren't supported with prerendering. See
  // https://crbug.com/40191159 for details.
  CHECK_NE(RenderFrameHostImpl::LifecycleStateImpl::kPrerendering,
           render_frame_host_impl->lifecycle_state());

  RenderFrameHostManager* inner_render_manager =
      inner_web_contents_impl->GetRenderManager();
  RenderFrameHostImpl* inner_main_frame =
      inner_render_manager->current_frame_host();
  RenderViewHostImpl* inner_render_view_host =
      inner_main_frame->render_view_host();
  RenderFrameHostImpl* inner_speculative_frame =
      inner_render_manager->speculative_frame_host();
  RenderViewHostImpl* inner_speculative_render_view_host =
      inner_speculative_frame ? inner_speculative_frame->render_view_host()
                              : nullptr;
  auto* outer_render_manager =
      render_frame_host_impl->frame_tree_node()->render_manager();

  // Make |render_frame_host_impl| an outer delegate frame.
  render_frame_host_impl->set_inner_tree_main_frame_tree_node_id(
      inner_main_frame->frame_tree_node()->frame_tree_node_id());

  // When attaching a WebContents as an inner WebContents, we need to replace
  // the Webcontents' view with a WebContentsViewChildFrame.
  inner_web_contents_impl->view_ = std::make_unique<WebContentsViewChildFrame>(
      inner_web_contents_impl,
      GetContentClient()->browser()->GetWebContentsViewDelegate(
          inner_web_contents_impl),
      &inner_web_contents_impl->render_view_host_delegate_view_);
  // On platforms where destroying the WebContents' view does not also destroy
  // the platform RenderWidgetHostView, we need to destroy it if it exists.
  // TODO(mcnee): Should all platforms' WebContentsView destroy the platform
  // RWHV?
  if (RenderWidgetHostViewBase* prev_rwhv =
          inner_render_manager->GetRenderWidgetHostView()) {
    if (!prev_rwhv->IsRenderWidgetHostViewChildFrame()) {
      prev_rwhv->Destroy();
    }
  }
  // Do the same for speculative render frame host's view.
  if (inner_speculative_frame) {
    RenderWidgetHostViewBase* prev_speculative_rwhv =
        static_cast<RenderWidgetHostViewBase*>(
            inner_speculative_frame->GetView());
    if (prev_speculative_rwhv &&
        !prev_speculative_rwhv->IsRenderWidgetHostViewChildFrame()) {
      prev_speculative_rwhv->Destroy();
    }
  }

  // When the WebContents being initialized has not already navigated, the
  // browser side Render{View,Frame}Host must be initialized and the
  // RenderWidgetHostView created. This is needed because the usual
  // initialization happens during the first navigation, but not all guest types
  // navigate before attaching. If the browser side is already initialized, the
  // calls below will just early return.
  inner_render_manager->InitRenderView(
      inner_main_frame->GetSiteInstance()->group(), inner_render_view_host,
      /*proxy=*/nullptr, /*navigation_metrics_token=*/std::nullopt);
  if (!inner_render_manager->GetRenderWidgetHostView()) {
    inner_web_contents_impl->CreateRenderWidgetHostViewForRenderManager(
        inner_render_view_host);
  }
  // Do the same for speculative render frame host.
  if (inner_speculative_render_view_host) {
    inner_render_manager->InitRenderView(
        inner_speculative_frame->GetSiteInstance()->group(),
        inner_speculative_render_view_host,
        /*proxy=*/nullptr, /*navigation_metrics_token=*/std::nullopt);
    RenderWidgetHostViewBase* speculative_rwhv =
        static_cast<RenderWidgetHostViewBase*>(
            inner_speculative_frame->GetView());
    if (!speculative_rwhv) {
      inner_web_contents_impl->CreateRenderWidgetHostViewForRenderManager(
          inner_speculative_render_view_host);
    }
  }

  inner_web_contents_impl->RecursivelyUnregisterRenderWidgetHostViews();

  // Create a link to our outer WebContents.
  node_.AttachInnerWebContents(inner_web_contents, render_frame_host_impl,
                               should_take_ownership);

  // Create a proxy in top-level RenderFrameHostManager, pointing to the
  // SiteInstanceGroup of the outer WebContents. The proxy will be used to send
  // postMessage to the inner WebContents.
  auto* proxy =
      inner_main_frame->browsing_context_state()->CreateOuterDelegateProxy(
          render_frame_host_impl->GetSiteInstance()->group(),
          inner_main_frame->frame_tree_node(), blink::RemoteFrameToken());
  // Since the inner WebContents is created from the browser side we do
  // not have RemoteFrame mojo channels. New channels will be bound when the
  // `CreateView` IPC is sent.

  // When attaching a GuestView as an inner WebContents, there should already be
  // a live RenderFrame, which has to be swapped.
  if (render_frame_host_impl->IsRenderFrameLive()) {
    inner_render_manager->SwapOuterDelegateFrame(
        render_frame_host_impl, proxy,
        inner_main_frame->devtools_frame_token());

    inner_web_contents_impl->ReattachToOuterWebContentsFrame();
  }

  if (primary_frame_tree_.GetFocusedFrame() ==
      render_frame_host_impl->frame_tree_node()) {
    inner_web_contents_impl->SetFocusedFrame(
        inner_web_contents_impl->primary_frame_tree_.root(),
        render_frame_host_impl->GetSiteInstance()->group());
  }
  outer_render_manager->set_attach_inner_delegate_complete();

  // If the inner WebContents is full frame, give it focus.
  if (is_full_page) {
    // There should only ever be one inner WebContents when |is_full_page| is
    // true, and it is the one we just attached.
    DCHECK_EQ(1u, node_.GetInnerWebContents().size());
    inner_web_contents_impl->SetAsFocusedWebContentsIfNecessary();
  }

  observers_.NotifyObservers(&WebContentsObserver::InnerWebContentsAttached,
                             inner_web_contents_impl, render_frame_host);

  // Make sure that the inner web contents and its outer delegate get properly
  // linked via the embedding token now that inner web contents are attached.
  inner_main_frame->PropagateEmbeddingTokenToParentFrame();
}

void WebContentsImpl::DetachUnownedInnerWebContents(
    base::PassKey<UnownedInnerWebContentsClient>,
    WebContents* inner_web_contents) {
  DetachUnownedInnerWebContents(inner_web_contents);
}

void WebContentsImpl::DetachUnownedInnerWebContents(
    WebContents* inner_web_contents) {
  CHECK(base::FeatureList::IsEnabled(features::kAttachUnownedInnerWebContents));
  CHECK(node_.IsUnownedInnerWebContents(inner_web_contents));

  WebContentsImpl* inner_web_contents_impl =
      static_cast<WebContentsImpl*>(inner_web_contents);
  // Unregister and destroy RenderWidgetHostViewChildFrame.
  inner_web_contents_impl->RecursivelyUnregisterRenderWidgetHostViews();

  // RenderWidgetHostView are of type RenderWidgetHostViewChildFrame and they
  // need to be re-created with appropriate platform views.
  std::vector<RenderViewHostImpl*> list_of_rvh_with_rwhv;
  inner_web_contents_impl->GetPrimaryFrameTree().ForEachRenderViewHost(
      [&list_of_rvh_with_rwhv](RenderViewHostImpl* rvh) {
        if (rvh->GetWidget() && rvh->GetWidget()->GetView()) {
          // While in theory only child frame RWHVs should exist at this stage,
          // in practice, a race with navigation cleanup could result in a main
          // frame RWHV that is pending deletion still existing here.
          // This might happen when a WebContents is destroyed immediately
          // after it navigates and then attaches to an outer WebContents.
          if (rvh->GetWidget()->GetView()->IsRenderWidgetHostViewChildFrame()) {
            list_of_rvh_with_rwhv.push_back(rvh);
          }
          rvh->GetWidget()->GetView()->Destroy();
        }
      });

  // Destroy WebContentsViewChildFrame.
  inner_web_contents_impl->render_view_host_delegate_view_ = nullptr;
  inner_web_contents_impl->view_ = nullptr;

  // Reset proxy.
  RenderFrameHostManager* inner_render_manager =
      inner_web_contents_impl->GetRenderManager();
  RenderFrameHostImpl* inner_main_frame =
      inner_render_manager->current_frame_host();
  RenderFrameProxyHost* proxy = inner_render_manager->GetProxyToOuterDelegate();
  if (proxy) {
    inner_main_frame->browsing_context_state()->DeleteRenderFrameProxyHost(
        proxy->site_instance_group(),
        BrowsingContextState::ProxyAccessMode::kAllowOuterDelegate);
  }

  node_.DetachInnerWebContents(inner_web_contents_impl);

  // Recreate WebContentsView.
  inner_web_contents_impl->view_ = CreateWebContentsView(
      inner_web_contents_impl,
      GetContentClient()->browser()->GetWebContentsViewDelegate(
          inner_web_contents_impl),
      &inner_web_contents_impl->render_view_host_delegate_view_);
  inner_web_contents_impl->view_->CreateView(gfx::NativeView());

  // Recreate and register RenderWidgetHostView. Don't do this if the
  // WebContents is being destroyed because it will cause a CHECK failure in
  // SendScreenRects().
  if (!inner_web_contents_impl->IsBeingDestroyed()) {
    for (RenderViewHostImpl* rvh : list_of_rvh_with_rwhv) {
      inner_web_contents_impl->CreateRenderWidgetHostViewForRenderManager(rvh);
    }
    inner_web_contents_impl->RecursivelyRegisterRenderWidgetHostViews();
  }

  inner_main_frame->UpdateAXTreeData();
}

void WebContentsImpl::AttachGuestPage(
    std::unique_ptr<GuestPageHolder> guest_page,
    RenderFrameHost* outer_render_frame_host) {
  CHECK(base::FeatureList::IsEnabled(features::kGuestViewMPArch));

  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::AttachGuestPage",
                        "guest_page", static_cast<void*>(guest_page.get()));
  auto* outer_render_frame_host_impl =
      static_cast<RenderFrameHostImpl*>(outer_render_frame_host);
  CHECK_EQ(this,
           WebContents::FromRenderFrameHost(outer_render_frame_host_impl));
  CHECK(outer_render_frame_host_impl->GetParent());

  // Guest pages aren't supported with prerendering. See
  // https://crbug.com/40191159 for details.
  CHECK_NE(RenderFrameHostImpl::LifecycleStateImpl::kPrerendering,
           outer_render_frame_host_impl->lifecycle_state());

  auto* guest_page_impl = static_cast<GuestPageHolderImpl*>(guest_page.get());
  outer_render_frame_host_impl->GetParent()->TakeGuestOwnership(
      base::WrapUnique(
          static_cast<GuestPageHolderImpl*>(guest_page.release())));

  FrameTree& inner_frame_tree = guest_page_impl->frame_tree();
  RenderFrameHostManager* inner_render_manager =
      inner_frame_tree.root()->render_manager();
  RenderFrameHostImpl* inner_main_frame =
      inner_render_manager->current_frame_host();
  RenderViewHostImpl* inner_render_view_host =
      inner_main_frame->render_view_host();
  auto* outer_render_manager =
      outer_render_frame_host_impl->frame_tree_node()->render_manager();

  if (RenderWidgetHostViewBase* prev_rwhv =
          inner_render_manager->GetRenderWidgetHostView()) {
    // Ensure that if there is an existing RenderWidgetHostView, it's valid to
    // embed.
    CHECK(prev_rwhv->IsRenderWidgetHostViewChildFrame());
    static_cast<RenderWidgetHostViewChildFrame*>(prev_rwhv)
        ->UnregisterFrameSinkId();
  }

  // Make `outer_render_frame_host_impl` the placeholder for the inner frame
  // tree.
  outer_render_frame_host_impl->set_inner_tree_main_frame_tree_node_id(
      inner_main_frame->frame_tree_node()->frame_tree_node_id());
  guest_page_impl->set_outer_frame_tree_node_id(
      outer_render_frame_host_impl->frame_tree_node()->frame_tree_node_id());

  // When the guest page being initialized has not already navigated, the
  // browser side Render{View,Frame}Host must be initialized and the
  // RenderWidgetHostView created. This is needed because the usual
  // initialization happens during the first navigation, but not all guest types
  // navigate before attaching. If the browser side is already initialized, the
  // call below will just early return.
  inner_render_manager->InitRenderView(
      inner_main_frame->GetSiteInstance()->group(), inner_render_view_host,
      /*proxy=*/nullptr, /*navigation_metrics_token=*/std::nullopt);

  // If we are reusing the RenderViewHost and it doesn't already have a
  // RenderWidgetHostView, we need to create one if this is the main frame.
  if (!inner_render_view_host->GetWidget()->GetView()) {
    // TODO(crbug.com/40162510): The RenderWidgetHostView should be created
    // *before* we create the renderer-side objects through InitRenderView().
    // Then we should remove the null-check for the RenderWidgetHostView in
    // RenderWidgetHostImpl::RendererWidgetCreated().
    CreateRenderWidgetHostViewForRenderManager(inner_render_view_host);
  }

  RenderFrameProxyHost* proxy =
      inner_main_frame->browsing_context_state()->CreateOuterDelegateProxy(
          outer_render_frame_host_impl->GetSiteInstance()->group(),
          inner_main_frame->frame_tree_node(), blink::RemoteFrameToken());
  // Since the inner page is created from the browser side we do
  // not have RemoteFrame mojo channels. New channels will be bound when the
  // `CreateView` IPC is sent.

  // When attaching a GuestView as an inner frame tree, there should already be
  // a live RenderFrame, which has to be swapped.
  if (outer_render_frame_host_impl->IsRenderFrameLive()) {
    inner_render_manager->SwapOuterDelegateFrame(
        outer_render_frame_host_impl, proxy,
        inner_main_frame->devtools_frame_token());
  }

  RenderWidgetHostViewBase* child_rwhvb =
      inner_render_manager->GetRenderWidgetHostView();
  CHECK(child_rwhvb);
  CHECK(child_rwhvb->IsRenderWidgetHostViewChildFrame());
  RenderWidgetHostViewChildFrame* child_rwhv =
      static_cast<RenderWidgetHostViewChildFrame*>(child_rwhvb);
  inner_render_manager->SetRWHViewForInnerFrameTree(child_rwhv);
  child_rwhv->RegisterFrameSinkId();

  outer_render_manager->set_attach_inner_delegate_complete();
  inner_main_frame->PropagateEmbeddingTokenToParentFrame();
  // TODO(crbug.com/40202416): Determine if anything else is needed here.
}

void WebContentsImpl::RecursivelyRegisterRenderWidgetHostViews() {
  OPTIONAL_TRACE_EVENT0(
      "content", "WebContentsImpl::RecursivelyRegisterRenderWidgetHostViews");

  auto* text_input_manager = GetTextInputManager();
  for (auto* view : GetRenderWidgetHostViewsInWebContentsTree()) {
    if (text_input_manager) {
      // Use RenderWidgetHostView::GetTextInputManager() for its side effects,
      // rather than registering the view directly; the view caches the
      // TextInputManager.
      //
      // TODO(crbug.com/40212969): This probably could be made more symmetrical
      // with unregistration. Getting rid of lazy registration might also allow
      // eliminating some special cases in TextInputManager.
      auto* text_input_manager_for_view = view->GetTextInputManager();
      DCHECK_EQ(text_input_manager, text_input_manager_for_view);
    }

    if (view->IsRenderWidgetHostViewChildFrame()) {
      static_cast<RenderWidgetHostViewChildFrame*>(view)->RegisterFrameSinkId();
    }
  }
}

void WebContentsImpl::RecursivelyUnregisterRenderWidgetHostViews() {
  OPTIONAL_TRACE_EVENT0(
      "content", "WebContentsImpl::RecursivelyUnregisterRenderWidgetHostViews");

  auto* text_input_manager = GetTextInputManager();
  for (auto* view : GetRenderWidgetHostViewsInWebContentsTree()) {
    if (text_input_manager) {
      // The RenderWidgetHostView will drop the cached TextInputManager itself.
      text_input_manager->Unregister(view);
    }

    if (view->IsRenderWidgetHostViewChildFrame()) {
      static_cast<RenderWidgetHostViewChildFrame*>(view)
          ->UnregisterFrameSinkId();
    }
  }
}

void WebContentsImpl::ReattachToOuterWebContentsFrame() {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::ReattachToOuterWebContentsFrame");
  DCHECK(node_.outer_web_contents());
  auto* render_manager = GetRenderManager();
  auto* child_rwhv = render_manager->GetRenderWidgetHostView();
  DCHECK(child_rwhv);
  DCHECK(child_rwhv->IsRenderWidgetHostViewChildFrame());
  render_manager->SetRWHViewForInnerFrameTree(
      static_cast<RenderWidgetHostViewChildFrame*>(child_rwhv));

  RecursivelyRegisterRenderWidgetHostViews();
  GetPrimaryMainFrame()->UpdateAXTreeData();
}

void WebContentsImpl::DidActivatePreviewedPage(
    base::TimeTicks activation_time) {
  TRACE_EVENT1("content", "WebContentsImpl::DidActivatePreviewedPage",
               "activation_time", activation_time);
  observers_.NotifyObservers(&WebContentsObserver::DidActivatePreviewedPage,
                             activation_time);
  GetDelegate()->DidActivatePreviewedPage();
}

void WebContentsImpl::DidChangeVisibleSecurityState() {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::DidChangeVisibleSecurityState");
  if (delegate_) {
    delegate_->VisibleSecurityStateChanged(this);
  }

  SCOPED_UMA_HISTOGRAM_TIMER(
      "WebContentsObserver.DidChangeVisibleSecurityState");
  observers_.NotifyObservers(
      &WebContentsObserver::DidChangeVisibleSecurityState);
}

const blink::web_pref::WebPreferences WebContentsImpl::ComputeWebPreferences(
    RenderFrameHostImpl* main_frame) {
  OPTIONAL_TRACE_EVENT0("browser", "WebContentsImpl::ComputeWebPreferences");
  CHECK(main_frame->is_main_frame());

  blink::web_pref::WebPreferences prefs;

  // Sets the hardware-related fields in |prefs| that are slow to compute. The
  // fields are set from cache if available, otherwise recomputed.
  SlowWebPreferenceCache::GetInstance()->Load(&prefs);

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

  prefs.web_security_enabled =
      !command_line.HasSwitch(switches::kDisableWebSecurity);

  prefs.remote_fonts_enabled =
      !command_line.HasSwitch(switches::kDisableRemoteFonts);
  prefs.local_storage_enabled =
      !command_line.HasSwitch(switches::kDisableLocalStorage);

  prefs.webgl1_enabled = !command_line.HasSwitch(switches::kDisable3DAPIs) &&
                         !command_line.HasSwitch(switches::kDisableWebGL);
  prefs.webgl2_enabled = !command_line.HasSwitch(switches::kDisable3DAPIs) &&
                         !command_line.HasSwitch(switches::kDisableWebGL) &&
                         !command_line.HasSwitch(switches::kDisableWebGL2);

  prefs.allow_file_access_from_file_urls =
      command_line.HasSwitch(switches::kAllowFileAccessFromFiles);

  prefs.accelerated_2d_canvas_enabled =
      !command_line.HasSwitch(switches::kDisableAccelerated2dCanvas);
  prefs.canvas_2d_layers_enabled =
      command_line.HasSwitch(switches::kEnableCanvas2DLayers) ||
      base::FeatureList::IsEnabled(features::kEnableCanvas2DLayers);
  prefs.antialiased_2d_canvas_disabled =
      command_line.HasSwitch(switches::kDisable2dCanvasAntialiasing);
  prefs.antialiased_clips_2d_canvas_enabled =
      !command_line.HasSwitch(switches::kDisable2dCanvasClipAntialiasing);

  prefs.disable_ipc_flooding_protection =
      command_line.HasSwitch(switches::kDisableIpcFloodingProtection) ||
      command_line.HasSwitch(switches::kDisablePushStateThrottle);

  prefs.accelerated_video_decode_enabled =
      !command_line.HasSwitch(switches::kDisableAcceleratedVideoDecode);

  std::string autoplay_policy = media::GetEffectiveAutoplayPolicy(command_line);
  if (autoplay_policy == switches::autoplay::kNoUserGestureRequiredPolicy) {
    prefs.autoplay_policy =
        blink::mojom::AutoplayPolicy::kNoUserGestureRequired;
  } else if (autoplay_policy ==
             switches::autoplay::kUserGestureRequiredPolicy) {
    prefs.autoplay_policy = blink::mojom::AutoplayPolicy::kUserGestureRequired;
  } else if (autoplay_policy ==
             switches::autoplay::kDocumentUserActivationRequiredPolicy) {
    prefs.autoplay_policy =
        blink::mojom::AutoplayPolicy::kDocumentUserActivationRequired;
  } else {
    NOTREACHED();
  }

  prefs.dont_send_key_events_to_javascript =
      base::FeatureList::IsEnabled(features::kDontSendKeyEventsToJavascript);

// TODO(dtapuska): Enable barrel button selection drag support on Android.
// crbug.com/758042
#if BUILDFLAG(IS_WIN)
  prefs.barrel_button_for_drag_enabled = true;
#endif  // BUILDFLAG(IS_WIN)

  prefs.enable_scroll_animator =
      command_line.HasSwitch(switches::kEnableSmoothScrolling) ||
      (!command_line.HasSwitch(switches::kDisableSmoothScrolling) &&
       gfx::Animation::ScrollAnimationsEnabledBySystem());

  prefs.prefers_reduced_motion = gfx::Animation::PrefersReducedMotion();

  const auto* const theme = ui::NativeTheme::GetInstanceForWeb();
  prefers_reduced_transparency_ = theme->prefers_reduced_transparency();
  inverted_colors_ = theme->inverted_colors();
  prefs.prefers_reduced_transparency = prefers_reduced_transparency_;
  prefs.inverted_colors = inverted_colors_;

  if (ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
          GetRenderViewHost()->GetProcess()->GetDeprecatedID())) {
    prefs.loads_images_automatically = true;
    prefs.javascript_enabled = true;
  }

  prefs.viewport_enabled = command_line.HasSwitch(switches::kEnableViewport);

#if BUILDFLAG(IS_ANDROID)
  // TODO(crbug.com/40925473): GetPrimaryDisplay() won't be correct for
  // externally connected displays. Get the display where Chrome is opened
  // instead.
  display::Display display = display::Screen::Get()->GetPrimaryDisplay();
  gfx::Size size = display.GetSizeInPixel();
  int min_width = size.width() < size.height() ? size.width() : size.height();
  int min_width_in_dp =
      static_cast<int>(min_width / display.device_scale_factor());
  if (prefs.viewport_enabled &&
      (ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_AUTOMOTIVE ||
       (min_width_in_dp >= kAndroidMinimumTabletWidthDp &&
        ui::GetDeviceFormFactor() != ui::DEVICE_FORM_FACTOR_TV))) {
    prefs.viewport_style = blink::mojom::ViewportStyle::kDefault;
  }
#endif

#if BUILDFLAG(IS_ANDROID)
  bool is_request_android_desktop_site = false;
#endif

  if (GetController().GetVisibleEntry() &&
      GetController().GetVisibleEntry()->GetIsOverridingUserAgent()) {
#if BUILDFLAG(IS_ANDROID)
    // Only ignore viewport meta tag when Request Desktop Site is used, but not
    // in other situations where embedder changes to arbitrary mobile UA string.
    is_request_android_desktop_site =
        renderer_preferences_.user_agent_override.ua_metadata_override &&
        !renderer_preferences_.user_agent_override.ua_metadata_override->mobile;
    prefs.viewport_meta_enabled = !is_request_android_desktop_site;
#else
    prefs.viewport_meta_enabled = false;
#endif
  }

  prefs.spatial_navigation_enabled =
      command_line.HasSwitch(switches::kEnableSpatialNavigation);

  if (is_spatial_navigation_disabled_) {
    prefs.spatial_navigation_enabled = false;
  }

#if BUILDFLAG(IS_ANDROID)
  prefs.long_press_link_select_text = long_press_link_select_text_;

  if (base::FeatureList::IsEnabled(
          features::kRestrictOrientationLockToPhones)) {
    // Only lock fullscreen orientation if the provider allows it, and if the
    // prefs currently want to do so.  While current behavior happens to match
    // exactly with the provider claiming to support orientation lock, we still
    // want to give the cache the opportunity to turn it off for other reasons.
    // For example, if a foldable is folded, then the prefs cache should notify
    // us that the behavior may have changed.
    prefs.video_fullscreen_orientation_lock_enabled &=
        screen_orientation_provider_->IsOrientationLockSupported();
  }
#endif

#if BUILDFLAG(IS_ANDROID)
  prefs.stylus_handwriting_enabled = stylus_handwriting_enabled_;
#elif BUILDFLAG(IS_WIN)
  prefs.stylus_handwriting_enabled =
      stylus_handwriting::win::IsStylusHandwritingWinEnabled();
#endif

  prefs.disable_reading_from_canvas =
      command_line.HasSwitch(switches::kDisableReadingFromCanvas);

  prefs.strict_mixed_content_checking =
      command_line.HasSwitch(switches::kEnableStrictMixedContentChecking);

  prefs.strict_powerful_feature_restrictions = command_line.HasSwitch(
      switches::kEnableStrictPowerfulFeatureRestrictions);

  const std::string blockable_mixed_content_group =
      base::FieldTrialList::FindFullName("BlockableMixedContent");
  prefs.strictly_block_blockable_mixed_content =
      blockable_mixed_content_group == "StrictlyBlockBlockableMixedContent";

  const std::string plugin_mixed_content_status =
      base::FieldTrialList::FindFullName("PluginMixedContentStatus");
  prefs.block_mixed_plugin_content =
      plugin_mixed_content_status == "BlockableMixedContent";

  prefs.v8_cache_options = GetV8CacheOptions();

  prefs.user_gesture_required_for_presentation = !command_line.HasSwitch(
      switches::kDisableGestureRequirementForPresentation);

  if (is_overlay_content_) {
    prefs.hide_download_ui = true;
  }

  // `media_controls_enabled` is `true` by default.
  if (has_persistent_video_) {
    prefs.media_controls_enabled = false;
  }

#if BUILDFLAG(IS_ANDROID)
  prefs.device_scale_adjustment = GetDeviceScaleAdjustment(min_width_in_dp);
#endif  // BUILDFLAG(IS_ANDROID)

  // GuestViews in the same StoragePartition need to find each other's frames.
  prefs.renderer_wide_named_frame_lookup =
      IsGuest() || main_frame->frame_tree()->is_guest();

  if (command_line.HasSwitch(switches::kHideScrollbars)) {
    prefs.hide_scrollbars = true;
  }

  prefs.payment_request_enabled =
      base::FeatureList::IsEnabled(features::kWebPayments);

#if BUILDFLAG(IS_ANDROID)
  if (base::FeatureList::IsEnabled(features::kWebauthnDisabledOnAuto) &&
      base::android::device_info::is_automotive()) {
    prefs.disable_webauthn = true;
  }
#endif  // BUILDFLAG(IS_ANDROID)

  // For devices that have larger displays (e.g. tablets, desktops), they
  // require a different set of webpref settings that is different from smaller
  // form-factors such as phones in order to render appropriately (e.g.
  // viewport)
#if BUILDFLAG(IS_ANDROID)
  if (base::FeatureList::IsEnabled(
          blink::features::kAndroidDesktopWebPrefsLargeDisplays)) {
    bool apply_desktop_common_settings = false;
    switch (ui::GetDeviceFormFactor()) {
      case ui::DEVICE_FORM_FACTOR_DESKTOP:
        apply_desktop_common_settings = true;
        // There are no orientation changes in desktop mode.
        // Might need to revisit for convertible devices (i.e. clamshell ->
        // tablet).
        prefs.main_frame_resizes_are_orientation_changes = false;
        break;
      case ui::DEVICE_FORM_FACTOR_TABLET:
        // Specific to large tablets (10"), by default they request desktop
        // site, but can per-site optionally override it to request mobile
        // instead.
        if (is_request_android_desktop_site) {
          apply_desktop_common_settings = true;
        }
        break;
      default:
        break;
    }

    if (apply_desktop_common_settings) {
      // Settings below matches up with desktop chrome

      // Set page scale factors to be similar to desktop.
      // The significant change compared to mobile is that we lock the min scale
      // to 1, so that we don't allow for a birds-eye-view zoom-out (this
      // matches desktop).
      prefs.default_minimum_page_scale_factor = 1.f;
      prefs.default_maximum_page_scale_factor = 4.f;

      // Ensure no further viewport scaling
      prefs.shrinks_viewport_contents_to_fit = false;
      // Not needed for larger form factors
      prefs.text_autosizing_enabled = false;
    }
  }

#endif  // BUILDFLAG(IS_ANDROID)

  GetContentClient()->browser()->OverrideWebPreferences(
      this, *main_frame->GetSiteInstance(), &prefs);
  return prefs;
}

void WebContentsImpl::OnWebPreferencesChanged() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::OnWebPreferencesChanged");

  // This is defensive code to avoid infinite loops due to code run inside
  // SetWebPreferences() accidentally updating more preferences and thus
  // calling back into this code. See crbug.com/398751 for one past example.
  if (updating_web_preferences_) {
    return;
  }
  updating_web_preferences_ = true;
  SetWebPreferences(ComputeWebPreferences(GetPrimaryMainFrame()));

#if BUILDFLAG(IS_ANDROID)
  const bool force_enable_zoom_changed =
      (force_enable_zoom_ != web_preferences_->force_enable_zoom);
  force_enable_zoom_ = web_preferences_->force_enable_zoom;
  if (force_enable_zoom_changed) {
    for (FrameTreeNode* node : primary_frame_tree_.Nodes()) {
      RenderFrameHostImpl* rfh = node->current_frame_host();
      if (rfh->is_local_root()) {
        if (auto* rwh = rfh->GetRenderWidgetHost()) {
          rwh->SetForceEnableZoom(force_enable_zoom_);
        }
      }
    }
  }
#endif

  // Update inner WebContents.
  for (WebContents* inner : GetInnerWebContents()) {
    static_cast<WebContentsImpl*>(inner)->OnWebPreferencesChanged();
  }

  updating_web_preferences_ = false;
}

void WebContentsImpl::NotifyPreferencesChanged() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::NotifyPreferencesChanged");

  // Recompute the WebPreferences based on the current state of the WebContents,
  // etc. Note that OnWebPreferencesChanged will also call SetWebPreferences and
  // send the updated WebPreferences to all RenderViews for this WebContents.
  OnWebPreferencesChanged();
}

void WebContentsImpl::SyncRendererPrefs() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::SyncRendererPrefs");

  ExecutePageBroadcastMethodForAllPages([this](RenderViewHostImpl* rvh) {
    rvh->SendRendererPreferencesToRenderer(GetRendererPrefs(rvh));
  });
}

void WebContentsImpl::OnCookiesAccessed(NavigationHandle* navigation,
                                        const CookieAccessDetails& details) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::OnCookiesAccessed",
                        "navigation_handle", navigation);
  // Use a variable to select between overloads.
  void (WebContentsObserver::*func)(NavigationHandle*,
                                    const CookieAccessDetails&) =
      &WebContentsObserver::OnCookiesAccessed;
  observers_.NotifyObservers(func, navigation, details);
}

void WebContentsImpl::OnCookiesAccessed(RenderFrameHostImpl* rfh,
                                        const CookieAccessDetails& details) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::OnCookiesAccessed",
                        "render_frame_host", rfh);
  // Use a variable to select between overloads.
  void (WebContentsObserver::*func)(RenderFrameHost*,
                                    const CookieAccessDetails&) =
      &WebContentsObserver::OnCookiesAccessed;
  observers_.NotifyObservers(func, rfh, details);
}

void WebContentsImpl::OnTrustTokensAccessed(
    NavigationHandle* navigation,
    const TrustTokenAccessDetails& details) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::OnTrustTokensAccessed",
                        "navigation_handle", navigation);
  // Use a variable to select between overloads.
  void (WebContentsObserver::*func)(NavigationHandle*,
                                    const TrustTokenAccessDetails&) =
      &WebContentsObserver::OnTrustTokensAccessed;
  observers_.NotifyObservers(func, navigation, details);
}

void WebContentsImpl::OnTrustTokensAccessed(
    RenderFrameHostImpl* rfh,
    const TrustTokenAccessDetails& details) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::OnTrustTokensAccessed",
                        "render_frame_host", rfh);
  // Use a variable to select between overloads.
  void (WebContentsObserver::*func)(RenderFrameHost*,
                                    const TrustTokenAccessDetails&) =
      &WebContentsObserver::OnTrustTokensAccessed;
  observers_.NotifyObservers(func, rfh, details);
}

void WebContentsImpl::OnSharedDictionaryAccessed(
    NavigationHandle* navigation,
    const network::mojom::SharedDictionaryAccessDetails& details) {
  OPTIONAL_TRACE_EVENT1("content",
                        "WebContentsImpl::OnSharedDictionaryAccessed",
                        "navigation_handle", navigation);
  // Use a variable to select between overloads.
  void (WebContentsObserver::*func)(
      NavigationHandle*, const network::mojom::SharedDictionaryAccessDetails&) =
      &WebContentsObserver::OnSharedDictionaryAccessed;
  observers_.NotifyObservers(func, navigation, details);
}

void WebContentsImpl::OnSharedDictionaryAccessed(
    RenderFrameHostImpl* rfh,
    const network::mojom::SharedDictionaryAccessDetails& details) {
  OPTIONAL_TRACE_EVENT1("content",
                        "WebContentsImpl::OnSharedDictionaryAccessed",
                        "render_frame_host", rfh);
  // Use a variable to select between overloads.
  void (WebContentsObserver::*func)(
      RenderFrameHost*, const network::mojom::SharedDictionaryAccessDetails&) =
      &WebContentsObserver::OnSharedDictionaryAccessed;
  observers_.NotifyObservers(func, rfh, details);
}

void WebContentsImpl::OnDeviceBoundSessionAccessed(
    NavigationHandle* navigation,
    const net::device_bound_sessions::SessionAccess& access) {
  OPTIONAL_TRACE_EVENT1("content",
                        "WebContentsImpl::OnDeviceBoundSessionAccessed",
                        "navigation_handle", navigation);
  // Use a variable to select between overloads.
  void (WebContentsObserver::*func)(
      NavigationHandle*, const net::device_bound_sessions::SessionAccess&) =
      &WebContentsObserver::OnDeviceBoundSessionAccessed;
  observers_.NotifyObservers(func, navigation, access);
}

void WebContentsImpl::OnDeviceBoundSessionAccessed(
    RenderFrameHostImpl* rfh,
    const net::device_bound_sessions::SessionAccess& access) {
  OPTIONAL_TRACE_EVENT1("content",
                        "WebContentsImpl::OnDeviceBoundSessionAccessed",
                        "render_frame_host", rfh);
  // Use a variable to select between overloads.
  void (WebContentsObserver::*func)(
      RenderFrameHost*, const net::device_bound_sessions::SessionAccess&) =
      &WebContentsObserver::OnDeviceBoundSessionAccessed;
  observers_.NotifyObservers(func, rfh, access);
}

void WebContentsImpl::NotifyStorageAccessed(
    RenderFrameHostImpl* rfh,
    blink::mojom::StorageTypeAccessed storage_type,
    bool blocked) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::NotifyStorageAccessed",
                        "render_frame_host", rfh);
  observers_.NotifyObservers(&WebContentsObserver::NotifyStorageAccessed, rfh,
                             storage_type, blocked);
}

void WebContentsImpl::OnVibrate(RenderFrameHostImpl* rfh) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::OnVibrate",
                        "render_frame_host", rfh);
  observers_.NotifyObservers(&WebContentsObserver::VibrationRequested);
}

std::optional<network::ParsedPermissionsPolicy>
WebContentsImpl::GetPermissionsPolicyForIsolatedWebApp(
    RenderFrameHostImpl* source) {
  WebExposedIsolationInfo weii =
      source->GetSiteInstance()->GetWebExposedIsolationInfo();
  CHECK(weii.is_isolated_application());
  return GetContentClient()->browser()->GetPermissionsPolicyForIsolatedWebApp(
      this, weii.origin());
}

void WebContentsImpl::Stop() {
  TRACE_EVENT0("content", "WebContentsImpl::Stop");
  ForEachFrameTree([](FrameTree& frame_tree) { frame_tree.StopLoading(); });
  GetPrerenderHostRegistry()->CancelAllHosts(PrerenderFinalStatus::kStop);
  observers_.NotifyObservers(&WebContentsObserver::NavigationStopped);
}

void WebContentsImpl::SetPageFrozen(bool frozen) {
  TRACE_EVENT1("content", "WebContentsImpl::SetPageFrozen", "frozen", frozen);

  // A visible page is never frozen.
  DCHECK_NE(Visibility::VISIBLE, GetVisibility());

  primary_frame_tree_.ForEachRenderViewHost(
      [&frozen](RenderViewHostImpl* rvh) { rvh->SetIsFrozen(frozen); });
}

std::unique_ptr<WebContents> WebContentsImpl::Clone() {
  TRACE_EVENT0("content", "WebContentsImpl::Clone");

  // We use our current SiteInstance since the cloned entry will use it anyway.
  // We pass our own opener so that the cloned page can access it if it was set
  // before.
  CreateParams create_params(GetBrowserContext(), GetSiteInstance());
  FrameTreeNode* opener = primary_frame_tree_.root()->opener();
  RenderFrameHostImpl* opener_rfh = nullptr;
  if (opener) {
    opener_rfh = opener->current_frame_host();
  }
  std::unique_ptr<WebContentsImpl> tc =
      CreateWithOpener(create_params, opener_rfh);
  tc->GetController().CopyStateFrom(&primary_frame_tree_.controller(), true);
  observers_.NotifyObservers(&WebContentsObserver::DidCloneToNewWebContents,
                             this, tc.get());
  return tc;
}

void WebContentsImpl::Init(const WebContents::CreateParams& params,
                           blink::FramePolicy primary_main_frame_policy) {
  TRACE_EVENT0("content", "WebContentsImpl::Init");

  // Set initial autofill mode. Prefs may update this value later but for
  // pre-warmed WebContents that update happens too late.
  renderer_preferences_.uses_platform_autofill =
      params.initially_use_platform_autofill;

  is_never_composited_ = params.is_never_composited;
  is_in_preview_mode_ = params.preview_mode;
  creator_location_ = params.creator_location;
#if BUILDFLAG(IS_ANDROID)
  java_creator_location_ = params.java_creator_location;
#endif  // BUILDFLAG(IS_ANDROID)

  if (params.picture_in_picture_options.has_value()) {
    picture_in_picture_options_ = params.picture_in_picture_options;
    if (GetOpener()) {
      picture_in_picture_opener_ =
          FromRenderFrameHostImpl(GetOpener())->GetWeakPtr();
    }
  }

  // This is set before initializing the render manager since
  // RenderFrameHostManager::Init calls back into us via its delegate to ask if
  // it should be hidden.
  visibility_ =
      params.initially_hidden ? Visibility::HIDDEN : Visibility::VISIBLE;
  GetController().SetActive(visibility_ == Visibility::VISIBLE);

  enable_wake_locks_ = params.enable_wake_locks;

  if (!params.last_active_time_ticks.is_null()) {
    last_active_time_ticks_ = params.last_active_time_ticks;
  }
  if (!params.last_active_time.is_null()) {
    last_active_time_ = params.last_active_time;
  }

  scoped_refptr<SiteInstanceImpl> site_instance =
      static_cast<SiteInstanceImpl*>(params.site_instance.get());
  if (!site_instance) {
    site_instance = SiteInstanceImpl::Create(params.browser_context);
  }
  if (params.desired_renderer_state == CreateParams::kNoRendererProcess) {
    site_instance->PreventAssociationWithSpareProcess();
  }

  // Iniitalize the primary FrameTree.
  // Note that GetOpener() is used here to get the opener for origin
  // inheritance, instead of other similar functions:
  // - GetOriginalOpener(), which would always return the main frame of the
  // opener, which might be different from the actual opener.
  // - FindOpenerRFH(), which will still return the opener frame if the
  // opener is suppressed (e.g. due to 'noopener'). The opener should not
  // be used for origin inheritance purposes in those cases, so this should
  // not pass the opener for those cases.
  primary_frame_tree_.Init(
      site_instance.get(), params.renderer_initiated_creation,
      params.main_frame_name, GetOpener(), primary_main_frame_policy,
      base::UnguessableToken::Create());

  std::unique_ptr<WebContentsViewDelegate> delegate =
      GetContentClient()->browser()->GetWebContentsViewDelegate(this);

  if (browser_plugin_guest_) {
    view_ = std::make_unique<WebContentsViewChildFrame>(
        this, std::move(delegate), &render_view_host_delegate_view_);
  } else {
    view_ = CreateWebContentsView(this, std::move(delegate),
                                  &render_view_host_delegate_view_);
  }
  CHECK(render_view_host_delegate_view_);
  CHECK(view_.get());

  // Set the accessibility mode after the view is created.
  if (!is_never_composited_) {
    BrowserAccessibilityStateImpl::GetInstance()->OnWebContentsInitialized(
        this);
  }

  view_->CreateView(params.context);

  screen_orientation_provider_ =
      std::make_unique<ScreenOrientationProvider>(this);

#if BUILDFLAG(IS_ANDROID) || (BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_IOS_TVOS))
  DateTimeChooser::CreateDateTimeChooser(this);
#endif

  // AttributionHost must be created after `view_->CreateView()` is called as it
  // may invoke `WebContentsAndroid::AddObserver()`.
  if (base::FeatureList::IsEnabled(
          attribution_reporting::features::kConversionMeasurement)) {
    AttributionHost::CreateForWebContents(this);
  }

  RedirectChainDetector::CreateForWebContents(this);
  BtmWebContentsObserver::MaybeCreateForWebContents(this);
  BtmNavigationFlowDetector::CreateForWebContents(this);
  RedirectHeuristicTabHelper::CreateForWebContents(this);
  OpenerHeuristicTabHelper::CreateForWebContents(this);

  // BrowserPluginGuest::Init needs to be called after this WebContents has
  // a RenderWidgetHostViewChildFrame. That is, |view_->CreateView| above.
  if (browser_plugin_guest_) {
    browser_plugin_guest_->Init();
  }

  g_created_callbacks.Get().Notify(this);

  // Create the renderer process in advance if requested.
  if (params.desired_renderer_state ==
      CreateParams::kInitializeAndWarmupRendererProcess) {
    if (!GetRenderManager()->current_frame_host()->IsRenderFrameLive()) {
      GetRenderManager()->InitRenderView(
          site_instance->group(), GetRenderViewHost(), /*proxy=*/nullptr,
          /*navigation_metrics_token=*/std::nullopt);
    }
  }

  // Let the embedder know about the newly created and initialized WebContents.
  GetContentClient()->browser()->OnWebContentsCreated(this);

  // Ensure that observers are notified of the creation of this WebContents's
  // main RenderFrameHost. It must be done here for main frames, since the
  // NotifySwappedFromRenderManager expects view_ to already be created and that
  // happens after RenderFrameHostManager::Init.
  NotifySwappedFromRenderManager(nullptr,
                                 GetRenderManager()->current_frame_host());

  // Checks whether the associated ssl_manager has any certificate error or HTTP
  // exceptions for any host and updates the renderer preferences.
  if (base::FeatureList::IsEnabled(
          features::kReduceSubresourceResponseStartedIPC) &&
      GetController().ssl_manager()->HasAllowExceptionForAnyHost()) {
    renderer_preferences_.send_subresource_notification = true;
    SyncRendererPrefs();
  }
}

void WebContentsImpl::OnWebContentsDestroyed(WebContentsImpl* web_contents) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::OnWebContentsDestroyed");

  RemoveWebContentsDestructionObserver(web_contents);

  // Clear a pending contents that has been closed before being shown.
  for (auto iter = pending_contents_.begin(); iter != pending_contents_.end();
       ++iter) {
    if (iter->second.contents.get() != web_contents) {
      continue;
    }

    // Someone else has deleted the WebContents. That should never happen!
    // TODO(erikchen): Fix semantics here. https://crbug.com/832879.
    iter->second.contents.release();
    pending_contents_.erase(iter);
    return;
  }
  NOTREACHED();
}

void WebContentsImpl::OnRenderWidgetHostDestroyed(
    RenderWidgetHost* render_widget_host) {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::OnRenderWidgetHostDestroyed");

  RemoveRenderWidgetHostDestructionObserver(render_widget_host);

  // Clear a pending widget that has been closed before being shown.
  size_t num_erased =
      std::erase_if(pending_widgets_, [render_widget_host](const auto& pair) {
        return pair.second == render_widget_host;
      });
  DCHECK_EQ(1u, num_erased);
}

void WebContentsImpl::AddWebContentsDestructionObserver(
    WebContentsImpl* web_contents) {
  OPTIONAL_TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("content.verbose"),
                        "WebContentsImpl::AddWebContentsDestructionObserver");

  if (!base::Contains(web_contents_destruction_observers_, web_contents)) {
    web_contents_destruction_observers_[web_contents] =
        std::make_unique<WebContentsDestructionObserver>(this, web_contents);
  }
}

void WebContentsImpl::RemoveWebContentsDestructionObserver(
    WebContentsImpl* web_contents) {
  OPTIONAL_TRACE_EVENT0(
      TRACE_DISABLED_BY_DEFAULT("content.verbose"),
      "WebContentsImpl::RemoveWebContentsDestructionObserver");
  web_contents_destruction_observers_.erase(web_contents);
}

void WebContentsImpl::AddRenderWidgetHostDestructionObserver(
    RenderWidgetHost* render_widget_host) {
  OPTIONAL_TRACE_EVENT0(
      TRACE_DISABLED_BY_DEFAULT("content.verbose"),
      "WebContentsImpl::AddRenderWidgetHostDestructionObserver");

  DCHECK(!base::Contains(render_widget_host_destruction_observers_,
                         render_widget_host));

  render_widget_host_destruction_observers_.insert(
      {render_widget_host,
       std::make_unique<RenderWidgetHostDestructionObserver>(
           this, render_widget_host)});
}

void WebContentsImpl::RemoveRenderWidgetHostDestructionObserver(
    RenderWidgetHost* render_widget_host) {
  OPTIONAL_TRACE_EVENT0(
      TRACE_DISABLED_BY_DEFAULT("content.verbose"),
      "WebContentsImpl::RemoveRenderWidgetHostDestructionObserver");
  render_widget_host_destruction_observers_.erase(render_widget_host);
}

void WebContentsImpl::AddObserver(WebContentsObserver* observer) {
  OPTIONAL_TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("content.verbose"),
                        "WebContentsImpl::AddObserver");
  observers_.AddObserver(observer);
}

void WebContentsImpl::RemoveObserver(WebContentsObserver* observer) {
  OPTIONAL_TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("content.verbose"),
                        "WebContentsImpl::RemoveObserver");
  observers_.RemoveObserver(observer);
}

std::set<RenderWidgetHostViewBase*>
WebContentsImpl::GetRenderWidgetHostViewsInWebContentsTree() {
  std::set<RenderWidgetHostViewBase*> result;
  // Views for speculative render frame host could also be frame sink id owner
  // and should move frame sink id registration from inner WebContents to outer
  // WebContents when WebContents is attached/detached.
  GetPrimaryMainFrame()->ForEachRenderFrameHostImplIncludingSpeculative(
      [&result](RenderFrameHostImpl* rfh) {
        if (auto* view =
                static_cast<RenderWidgetHostViewBase*>(rfh->GetView())) {
          result.insert(view);
        }
      });
  return result;
}

void WebContentsImpl::Activate() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::Activate");
  if (delegate_) {
    delegate_->ActivateContents(this);
  }
}

void WebContentsImpl::SetTopControlsShownRatio(
    RenderWidgetHostImpl* render_widget_host,
    float ratio) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::SetTopControlsShownRatio",
                        "render_widget_host", render_widget_host, "ratio",
                        ratio);
  if (!delegate_) {
    return;
  }

  RenderFrameHostImpl* rfh = GetPrimaryMainFrame();
  if (!rfh || render_widget_host != rfh->GetRenderWidgetHost()) {
    return;
  }

  delegate_->SetTopControlsShownRatio(this, ratio);
}

void WebContentsImpl::SetTopControlsGestureScrollInProgress(bool in_progress) {
  OPTIONAL_TRACE_EVENT1(
      "content", "WebContentsImpl::SetTopControlsGestureScrollInProgress",
      "in_progress", in_progress);
  if (delegate_) {
    delegate_->SetTopControlsGestureScrollInProgress(in_progress);
  }
}

void WebContentsImpl::RenderWidgetCreated(
    RenderWidgetHostImpl* render_widget_host) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::RenderWidgetCreated",
                        "render_widget_host", render_widget_host);
  created_widgets_[render_widget_host->GetFrameSinkId()] = render_widget_host;
}

void WebContentsImpl::RenderWidgetDeleted(
    RenderWidgetHostImpl* render_widget_host) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::RenderWidgetDeleted",
                        "render_widget_host", render_widget_host);
  // Note that IsBeingDestroyed() can return true at this point as
  // ~WebContentsImpl() calls RFHM::ClearRFHsPendingShutdown(), which might lead
  // us here.
  created_widgets_.erase(render_widget_host->GetFrameSinkId());

  if (IsBeingDestroyed()) {
    return;
  }

  if (render_widget_host == pointer_lock_widget_) {
    LostPointerLock(pointer_lock_widget_);
  }

  CancelKeyboardLock(render_widget_host);
}

void WebContentsImpl::RenderWidgetWasResized(
    RenderWidgetHostImpl* render_widget_host,
    bool width_changed) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::RenderWidgetWasResized",
                        "render_widget_host", render_widget_host,
                        "width_changed", width_changed);
  RenderFrameHostImpl* rfh = GetPrimaryMainFrame();
  if (!rfh || render_widget_host != rfh->GetRenderWidgetHost()) {
    return;
  }

  observers_.NotifyObservers(&WebContentsObserver::PrimaryMainFrameWasResized,
                             width_changed);
}

void WebContentsImpl::PreHandleDragUpdate(const DropData& drop_data,
                                          const gfx::PointF& client_pt) {
  if (delegate_) {
    delegate_->PreHandleDragUpdate(drop_data, client_pt);
  }
}

void WebContentsImpl::PreHandleDragExit() {
  if (delegate_) {
    delegate_->PreHandleDragExit();
  }
}

KeyboardEventProcessingResult WebContentsImpl::PreHandleKeyboardEvent(
    const input::NativeWebKeyboardEvent& event) {
  OPTIONAL_TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("content.verbose"),
                        "WebContentsImpl::PreHandleKeyboardEvent");
  auto* outermost_contents = GetOutermostWebContents();
  // TODO(wjmaclean): Generalize this to forward all key events to the outermost
  // delegate's handler.
  if (outermost_contents != this && IsFullscreen() &&
      event.windows_key_code == ui::VKEY_ESCAPE) {
    // When an inner WebContents has focus and is fullscreen, redirect <esc>
    // key events to the outermost WebContents so it can be handled by that
    // WebContents' delegate.
    if (outermost_contents->PreHandleKeyboardEvent(event) ==
        KeyboardEventProcessingResult::HANDLED) {
      return KeyboardEventProcessingResult::HANDLED;
    }
  }
  return delegate_ ? delegate_->PreHandleKeyboardEvent(this, event)
                   : KeyboardEventProcessingResult::NOT_HANDLED;
}

bool WebContentsImpl::HandleMouseEvent(const blink::WebMouseEvent& event) {
  OPTIONAL_TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("content.verbose"),
                        "WebContentsImpl::HandleMouseEvent");
  // Handle mouse button back/forward in the browser process after the render
  // process is done with the event. This ensures all renderer-initiated history
  // navigations can be treated consistently.
  if (event.GetType() == blink::WebInputEvent::Type::kMouseUp) {
    WebContentsImpl* outermost = GetOutermostWebContents();
    if (event.button == blink::WebPointerProperties::Button::kBack &&
        outermost->GetController().CanGoBack()) {
      outermost->GetController().GoBack();
      return true;
    } else if (event.button == blink::WebPointerProperties::Button::kForward &&
               outermost->GetController().CanGoForward()) {
      outermost->GetController().GoForward();
      return true;
    }
  }
  return false;
}

bool WebContentsImpl::HandleKeyboardEvent(
    const input::NativeWebKeyboardEvent& event) {
  OPTIONAL_TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("content.verbose"),
                        "WebContentsImpl::HandleKeyboardEvent");
  if (browser_plugin_embedder_ &&
      browser_plugin_embedder_->HandleKeyboardEvent(event)) {
    return true;
  }
  return delegate_ && delegate_->HandleKeyboardEvent(this, event);
}

bool WebContentsImpl::HandleWheelEvent(const blink::WebMouseWheelEvent& event) {
  OPTIONAL_TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("content.verbose"),
                        "WebContentsImpl::HandleWheelEvent");
#if !BUILDFLAG(IS_MAC)
  // On platforms other than Mac, control+mousewheel may change zoom. On Mac,
  // this isn't done for two reasons:
  //   -the OS already has a gesture to do this through pinch-zoom
  //   -if a user starts an inertial scroll, let's go, and presses control
  //      (i.e. control+tab) then the OS's buffered scroll events will come in
  //      with control key set which isn't what the user wants
  if (delegate_ && event.wheel_ticks_y &&
      event.event_action == blink::WebMouseWheelEvent::EventAction::kPageZoom) {
    // Count only integer cumulative scrolls as zoom events; this handles
    // smooth scroll and regular scroll device behavior.
    zoom_scroll_remainder_ += event.wheel_ticks_y;
    int whole_zoom_scroll_remainder_ = std::lround(zoom_scroll_remainder_);
    zoom_scroll_remainder_ -= whole_zoom_scroll_remainder_;
    if (whole_zoom_scroll_remainder_ != 0) {
      delegate_->ContentsZoomChange(whole_zoom_scroll_remainder_ > 0);
    }
    return true;
  }
#endif
  return false;
}

bool WebContentsImpl::PreHandleGestureEvent(
    const blink::WebGestureEvent& event) {
  OPTIONAL_TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("content.verbose"),
                        "WebContentsImpl::PreHandleGestureEvent");
  return delegate_ && delegate_->PreHandleGestureEvent(this, event);
}

input::RenderWidgetHostInputEventRouter*
WebContentsImpl::GetInputEventRouter() {
  if (!IsBeingDestroyed()) {
    if (GetOuterWebContents()) {
      return GetOuterWebContents()->GetInputEventRouter();
    }

    if (!rwh_input_event_router_.get()) {
      rwh_input_event_router_ =
          MakeRefCounted<input::RenderWidgetHostInputEventRouter>(
              GetHostFrameSinkManager(), this);
    }
  }
  return rwh_input_event_router_.get();
}

void WebContentsImpl::GetRenderWidgetHostAtPointAsynchronously(
    RenderWidgetHostViewBase* root_view,
    const gfx::PointF& point,
    base::OnceCallback<void(base::WeakPtr<RenderWidgetHostViewBase>,
                            std::optional<gfx::PointF>)> callback) {
  GetInputEventRouter()->GetRenderWidgetHostAtPointAsynchronously(
      root_view, point, base::BindOnce(&RunCallback, std::move(callback)));
}

std::vector<RenderWidgetHostView*>
WebContentsImpl::GetRenderWidgetHostViewsForTests() {
  auto input_hosts =
      GetInputEventRouter()->GetRenderWidgetHostViewInputsForTests();
  std::vector<RenderWidgetHostView*> hosts;
  for (auto host : input_hosts) {
    hosts.push_back(static_cast<RenderWidgetHostViewBase*>(host));
  }
  return hosts;
}

RenderWidgetHostImpl* WebContentsImpl::GetFocusedRenderWidgetHost(
    RenderWidgetHostImpl* receiving_widget) {
  // Events for widgets other than the main frame (e.g., popup menus) should be
  // forwarded directly to the widget they arrived on.
  if (receiving_widget != GetPrimaryMainFrame()->GetRenderWidgetHost()) {
    return receiving_widget;
  }

  // If the focused WebContents is a guest WebContents, then get the focused
  // frame in the embedder WebContents instead.
  FrameTreeNode* focused_frame = GetFocusedFrameTree()->GetFocusedFrame();

  if (!focused_frame) {
    return receiving_widget;
  }

  // The view may be null if a subframe's renderer process has crashed while
  // the subframe has focus.  Drop the event in that case.  Do not give
  // it to the main frame, so that the user doesn't unexpectedly type into the
  // wrong frame if a focused subframe renderer crashes while they type.
  RenderWidgetHostView* view = focused_frame->current_frame_host()->GetView();
  if (!view) {
    return nullptr;
  }

  return RenderWidgetHostImpl::From(view->GetRenderWidgetHost());
}

RenderWidgetHostImpl* WebContentsImpl::GetRenderWidgetHostWithPageFocus() {
  FrameTree* focused_frame_tree = GetFocusedFrameTree();
  return focused_frame_tree->root()
      ->current_frame_host()
      ->GetRenderWidgetHost();
}

bool WebContentsImpl::CanEnterFullscreenMode(
    RenderFrameHostImpl* requesting_frame) {
  // It's possible that this WebContents was spawned while blocking UI was on
  // the screen, or that it was downstream from a WebContents when UI was
  // blocked. Therefore, disqualify it from fullscreen if it or any upstream
  // WebContents has an active blocker.
  return delegate_ &&
         std::ranges::all_of(GetAllOpeningWebContents(this),
                             [](auto* opener) {
                               return opener->fullscreen_blocker_count_ == 0;
                             }) &&
         delegate_->CanEnterFullscreenModeForTab(requesting_frame);
}

void WebContentsImpl::EnterFullscreenMode(
    RenderFrameHostImpl* requesting_frame,
    const blink::mojom::FullscreenOptions& options) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::EnterFullscreenMode");
  DCHECK(CanEnterFullscreenMode(requesting_frame));
  DCHECK(requesting_frame->IsActive());
  DCHECK(ContainsOrIsFocusedWebContents());
  // Ensure the window is made active to take input focus. The window may be
  // inactive when sites request fullscreen via capability delegation, consume
  // transient activation from a gesture made before another window was focused,
  // or if the site has been granted the Automatic Fullscreen content setting.
  // Note: requests by inactive tabs of multi-tab windows are rejected earlier.
  Activate();

  // When WebView is the `delegate_` we can end up with VisualProperties changes
  // synchronously. Notify the view ahead so it can handle the transition.
  if (auto* view = GetRenderWidgetHostView()) {
    static_cast<RenderWidgetHostViewBase*>(view)->EnterFullscreenMode(options);
  }

  if (delegate_) {
    delegate_->EnterFullscreenModeForTab(requesting_frame, options);

    if (keyboard_lock_widget_) {
      delegate_->RequestKeyboardLock(this, esc_key_locked_);
    }
  }

  observers_.NotifyObservers(
      &WebContentsObserver::DidToggleFullscreenModeForTab, IsFullscreen(),
      false);
  FullscreenContentsSet(GetBrowserContext())->insert(this);
}

void WebContentsImpl::ExitFullscreenMode(bool will_cause_resize) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::ExitFullscreenMode",
                        "will_cause_resize", will_cause_resize);
  // When WebView is the `delegate_` we can end up with VisualProperties changes
  // synchronously. Notify the view ahead so it can handle the transition.
  if (auto* view = GetRenderWidgetHostView()) {
    static_cast<RenderWidgetHostViewBase*>(view)->ExitFullscreenMode();
  }

  GetFullscreenUserData(GetBrowserContext())
      ->last_exits()
      ->insert_or_assign(GetPrimaryMainFrame()->GetLastCommittedOrigin(),
                         base::TimeTicks::Now());

  if (delegate_) {
    // This may spin the message loop and destroy this object crbug.com/1506535
    base::WeakPtr<WebContentsImpl> weak_ptr = weak_factory_.GetWeakPtr();
    delegate_->ExitFullscreenModeForTab(this);
    if (!weak_ptr) {
      return;
    }

    if (keyboard_lock_widget_) {
      delegate_->CancelKeyboardLockRequest(this);
    }
  }

  // The fullscreen state is communicated to the renderer through a resize
  // message. If the change in fullscreen state doesn't cause a view resize
  // then we must ensure web contents exit the fullscreen state by explicitly
  // sending a resize message. This is required for the situation of the browser
  // moving the view into a "browser fullscreen" state and then the contents
  // entering "tab fullscreen". Exiting the contents "tab fullscreen" then won't
  // have the side effect of the view resizing, hence the explicit call here is
  // required.
  if (!will_cause_resize) {
    if (RenderWidgetHostView* rwhv = GetRenderWidgetHostView()) {
      if (RenderWidgetHost* render_widget_host = rwhv->GetRenderWidgetHost()) {
        render_widget_host->SynchronizeVisualProperties();
      }
    }
  }

  current_fullscreen_frame_id_ = GlobalRenderFrameHostId();

  observers_.NotifyObservers(
      &WebContentsObserver::DidToggleFullscreenModeForTab, IsFullscreen(),
      will_cause_resize);

  if (safe_area_insets_host_) {
    safe_area_insets_host_->DidExitFullscreen();
  }

  FullscreenContentsSet(GetBrowserContext())->erase(this);
}

void WebContentsImpl::FullscreenStateChanged(
    RenderFrameHostImpl* rfh,
    bool is_fullscreen,
    blink::mojom::FullscreenOptionsPtr options) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::FullscreenStateChanged",
                        "render_frame_host", rfh, "is_fullscreen",
                        is_fullscreen);

  GetView()->FullscreenStateChanged(is_fullscreen);

  if (is_fullscreen) {
    if (options.is_null()) {
      ReceivedBadMessage(rfh->GetProcess(),
                         bad_message::WCI_INVALID_FULLSCREEN_OPTIONS);
      return;
    }

    if (delegate_) {
      delegate_->FullscreenStateChangedForTab(rfh, *options);
    }

    if (bool was_inserted = fullscreen_frames_.insert(rfh).second;
        was_inserted) {
      FullscreenFrameSetUpdated();
    }
    return;
  }

  // If |rfh| is no longer in fullscreen, remove it and any descendants.
  // See https://fullscreen.spec.whatwg.org.
  size_t size_before_deletion = fullscreen_frames_.size();
  std::erase_if(fullscreen_frames_, [&](RenderFrameHostImpl* current) {
    while (current) {
      if (current == rfh) {
        return true;
      }
      // We only look for direct parents. fencedframes will not enter
      // fullscreen.
      current = current->GetParent();
    }
    return false;
  });

  if (size_before_deletion != fullscreen_frames_.size()) {
    FullscreenFrameSetUpdated();
  }
}

bool WebContentsImpl::CanUseWindowingControls(
    RenderFrameHostImpl* requesting_frame) {
  return GetDelegate() &&
         GetDelegate()->CanUseWindowingControls(requesting_frame);
}

void WebContentsImpl::Maximize() {
  if (!GetDelegate()) {
    return;
  }
  GetDelegate()->MaximizeFromWebAPI();
}

void WebContentsImpl::Minimize() {
  if (!GetDelegate()) {
    return;
  }
  GetDelegate()->MinimizeFromWebAPI();
}

void WebContentsImpl::Restore() {
  if (!GetDelegate()) {
    return;
  }
  GetDelegate()->RestoreFromWebAPI();
}

// TODO(laurila, crbug.com/1466855): Map into new `ui::DisplayState` enum
// instead of `ui::mojom::WindowShowState`.
ui::mojom::WindowShowState WebContentsImpl::GetWindowShowState() {
  return GetDelegate() ? GetDelegate()->GetWindowShowState()
                       : ui::mojom::WindowShowState::kDefault;
}

blink::mojom::DevicePostureProvider*
WebContentsImpl::GetDevicePostureProvider() {
  return DevicePostureProviderImpl::GetOrCreate(this);
}

bool WebContentsImpl::GetResizable() {
  return GetDelegate() && GetDelegate()->GetCanResize();
}

void WebContentsImpl::FullscreenFrameSetUpdated() {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::FullscreenFrameSetUpdated");
  if (fullscreen_frames_.empty()) {
    current_fullscreen_frame_id_ = GlobalRenderFrameHostId();
    return;
  }

  // Find the current fullscreen frame and call the observers.
  // If frame A is fullscreen, then frame B goes into inner fullscreen, then B
  // exits fullscreen - that will result in A being fullscreen.
  RenderFrameHostImpl* new_fullscreen_frame = *std::max_element(
      fullscreen_frames_.begin(), fullscreen_frames_.end(), FrameCompareDepth);

  // If we have already notified observers about this frame then we should not
  // fire the observers again.
  if (new_fullscreen_frame->GetGlobalId() == current_fullscreen_frame_id_) {
    return;
  }
  current_fullscreen_frame_id_ = new_fullscreen_frame->GetGlobalId();

  observers_.NotifyObservers(&WebContentsObserver::DidAcquireFullscreen,
                             new_fullscreen_frame);
  if (safe_area_insets_host_) {
    safe_area_insets_host_->DidAcquireFullscreen(new_fullscreen_frame);
  }
}

PageVisibilityState WebContentsImpl::CalculatePageVisibilityState(
    Visibility visibility) const {
  // Only hide the page if there are no entities capturing screenshots
  // or video (e.g. mirroring or WebXR). If there are, apply the correct state
  // of kHidden or kHiddenButPainting.
  bool web_contents_visible_in_vr = false;
#if BUILDFLAG(ENABLE_VR)
  web_contents_visible_in_vr =
      XRRuntimeManagerImpl::GetImmersiveSessionWebContents() == this;
#endif

  // If there are entities in Picture-in-Picture mode, don't activate the
  // "disable rendering" optimization, since it still needs to drive the video,
  // and possibly other elements on the page like canvas, to keep the picture in
  // picture window up to date.
  if (visibility == Visibility::VISIBLE || visible_capturer_count_ > 0 ||
      web_contents_visible_in_vr) {
    return PageVisibilityState::kVisible;
  } else if (hidden_capturer_count_ > 0 || has_picture_in_picture_video_ ||
             has_picture_in_picture_document_) {
    return PageVisibilityState::kHiddenButPainting;
  }
  return PageVisibilityState::kHidden;
}

PageVisibilityState WebContentsImpl::GetPageVisibilityState() const {
  return CalculatePageVisibilityState(visibility_);
}

void WebContentsImpl::UpdateVisibilityAndNotifyPageAndView(
    Visibility new_visibility,
    bool is_activity) {
  DCHECK(!IsBeingDestroyed());

  PageVisibilityState page_visibility =
      CalculatePageVisibilityState(new_visibility);

  // A crashed frame might be covered by a sad tab. See docs on SadTabHelper
  // exactly when it is or isn't. Either way, don't make it visible.
  bool view_is_visible =
      !IsCrashed() && page_visibility != PageVisibilityState::kHidden;

  // True if the instance is being hidden or revealed.
  const bool hide_or_reveal = (visibility_ == Visibility::HIDDEN) !=
                              (new_visibility == Visibility::HIDDEN);

  // Send ax modes to renderers before they start painting if they are being
  // revealed.
  if (!is_never_composited_ && hide_or_reveal &&
      new_visibility != Visibility::HIDDEN) {
    BrowserAccessibilityStateImpl::GetInstance()->OnWebContentsRevealed(this);
  }

  // Prerendering relies on overriding FrameTree::Delegate::IsHidden,
  // while for other frame trees FrameTree::Delegate::IsHidden
  // resolves to WebContents' visibility, so we avoid Prerender RennderViewHosts
  // here.
  ForEachRenderViewHostTypes view_mask =
      static_cast<ForEachRenderViewHostTypes>(
          ForEachRenderViewHostTypes::kBackForwardCacheViews |
          ForEachRenderViewHostTypes::kActiveViews);

  RenderViewHostIterationCallback update_frame_tree_visibility =
      base::BindRepeating(
          [](PageVisibilityState page_visibility,
             RenderViewHostImpl* render_view_host) {
            // If we are a guest frame tree, allow the visibility (ie
            // display:none) to override the page visibility.
            if (render_view_host->frame_tree()->is_guest()) {
              RenderFrameProxyHost* proxy = render_view_host->frame_tree()
                                                ->root()
                                                ->render_manager()
                                                ->GetProxyToOuterDelegate();
              if (proxy && proxy->cross_process_frame_connector()->IsHidden()) {
                page_visibility = PageVisibilityState::kHidden;
              }
            }

            render_view_host->SetFrameTreeVisibility(page_visibility);
          },
          page_visibility);

  if (page_visibility != PageVisibilityState::kHidden) {
    // This shows the Page before showing the individual RenderWidgets, as
    // RenderWidgets will work to produce compositor frames and handle input
    // as soon as they are shown. But the Page and other classes do not expect
    // to be producing frames when the Page is hidden. So we make sure the Page
    // is shown first.
    ForEachRenderViewHost(view_mask, update_frame_tree_visibility);
  }

  // |GetRenderWidgetHostView()| can be null if the user middle clicks a link to
  // open a tab in the background, then closes the tab before selecting it.
  // This is because closing the tab calls WebContentsImpl::Destroy(), which
  // removes the |GetRenderViewHost()|; then when we actually destroy the
  // window, OnWindowPosChanged() notices and calls WasHidden() (which
  // calls us).
  if (auto* view = GetRenderWidgetHostView()) {
    if (view_is_visible) {
      static_cast<RenderWidgetHostViewBase*>(view)->ShowWithVisibility(
          page_visibility);
    } else if (new_visibility == Visibility::HIDDEN) {
      view->Hide();
    } else {
      view->WasOccluded();
    }
  }

  SetVisibilityForChildViews(view_is_visible);

  // Make sure to call SetVisibilityAndNotifyObservers(VISIBLE) before notifying
  // the CrossProcessFrameConnector.
  if (new_visibility == Visibility::VISIBLE) {
    if (is_activity) {
      last_active_time_ticks_ = base::TimeTicks::Now();
      last_active_time_ = base::Time::Now();
    }
    SetVisibilityAndNotifyObservers(new_visibility);
  }

  if (page_visibility == PageVisibilityState::kHidden) {
    // Similar to when showing the page, we only hide the page after
    // hiding the individual RenderWidgets.
    ForEachRenderViewHost(view_mask, update_frame_tree_visibility);
  }

  if (new_visibility != Visibility::VISIBLE) {
    SetVisibilityAndNotifyObservers(new_visibility);
  }

  if (base::FeatureList::IsEnabled(kUpdateInnerWebContentsVisibility)) {
    // Inner WebContents are skipped in ForEachRenderViewHost() above, which
    // causes inner WebContents to not be notified of visibility changes.
    //
    // Note: An inner WebContents that is hidden within the embedder could
    // spuriously be set to visible (e.g. if its parent is display:none), but
    // this is ignored here for now.
    for (WebContents* inner : GetInnerWebContents()) {
      static_cast<WebContentsImpl*>(inner)
          ->UpdateVisibilityAndNotifyPageAndView(new_visibility, is_activity);
    }
  }

  if (!is_never_composited_ && hide_or_reveal &&
      new_visibility == Visibility::HIDDEN) {
    BrowserAccessibilityStateImpl::GetInstance()->OnWebContentsHidden(this);
  }

  // We cannot show a page or capture video unless there is a valid renderer
  // associated with this web contents. The navigation controller for this page
  // must be set to active (allowing navigation to complete, a renderer and its
  // associated views to be created, etc.) if any of these conditions holds.
  //
  // Previously, it was possible for browser-side code to try to capture video
  // from a restored tab (for a variety of reasons, including the browser
  // creating preview thumbnails) and the tab would never actually load. By
  // keying this behavior off of |page_visibility| instead of just
  // |new_visibility| we avoid this case. See crbug.com/1020782 for more
  // context.
  //
  // SetActive() can immediately begin a navigation, synchronously emitting the
  // relevant events. Ensure this is done after the WebContents has successfully
  // transitioned to the visible state. See crbug.com/383189046 for details.
  GetController().SetActive(page_visibility != PageVisibilityState::kHidden);

  // DelegateWasShown() keeps track of crash metrics. This is safe to call for
  // GuestViews, and inner frame trees. Call this only after visibility changes
  // and navigations have been processed to ensure clients have all information
  // necessary to log the correct crash metrics.
  if (page_visibility != PageVisibilityState::kHidden) {
    for (FrameTreeNode* node :
         FrameTree::SubtreeAndInnerTreeNodes(GetPrimaryMainFrame())) {
      if (RenderFrameProxyHost* proxy_to_parent_or_outer_delegate =
              node->render_manager()->GetProxyToParentOrOuterDelegate()) {
        proxy_to_parent_or_outer_delegate->cross_process_frame_connector()
            ->DelegateWasShown();
      }
    }
  }
}

#if BUILDFLAG(IS_ANDROID)
void WebContentsImpl::UpdateUserGestureCarryoverInfo() {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::UpdateUserGestureCarryoverInfo");
  if (delegate_) {
    delegate_->UpdateUserGestureCarryoverInfo(this);
  }
}
#endif

bool WebContentsImpl::IsFullscreen() {
  return delegate_ && delegate_->IsFullscreenForTabOrPending(this);
}

bool WebContentsImpl::ShouldShowStaleContentOnEviction() {
  return GetDelegate() && GetDelegate()->ShouldShowStaleContentOnEviction(this);
}

blink::mojom::DisplayMode WebContentsImpl::GetDisplayMode() const {
  return delegate_ ? delegate_->GetDisplayMode(this)
                   : blink::mojom::DisplayMode::kBrowser;
}

void WebContentsImpl::RequestToLockPointer(
    RenderWidgetHostImpl* render_widget_host,
    bool user_gesture,
    bool last_unlocked_by_target) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::RequestPointerLock",
                        "render_widget_host", render_widget_host);
  if (render_widget_host->frame_tree()->is_fenced_frame()) {
    // The renderer should have checked and disallowed the request for fenced
    // frames in PointerLockController and dispatched pointerlockerror. Ignore
    // the request and mark it as bad if it didn't happen for some reason.
    ReceivedBadMessage(render_widget_host->GetProcess(),
                       bad_message::WCI_REQUEST_LOCK_MOUSE_FENCED_FRAME);
    return;
  }
  for (WebContentsImpl* current = this; current;
       current = current->GetOuterWebContents()) {
    if (current->pointer_lock_widget_) {
      render_widget_host->GotResponseToPointerLockRequest(
          blink::mojom::PointerLockResult::kAlreadyLocked);
      return;
    }
  }

  bool widget_in_frame_tree = false;
  for (FrameTreeNode* node : primary_frame_tree_.Nodes()) {
    if (node->current_frame_host()->GetRenderWidgetHost() ==
        render_widget_host) {
      widget_in_frame_tree = true;
      break;
    }
  }

  if (widget_in_frame_tree && delegate_) {
    for (WebContentsImpl* current = this; current;
         current = current->GetOuterWebContents()) {
      current->pointer_lock_widget_ = render_widget_host;
    }
    observers_.NotifyObservers(&WebContentsObserver::PointerLockRequested);
    delegate_->RequestPointerLock(this, user_gesture, last_unlocked_by_target);
  } else {
    render_widget_host->GotResponseToPointerLockRequest(
        blink::mojom::PointerLockResult::kWrongDocument);
  }
}

bool WebContentsImpl::IsWaitingForPointerLockPrompt(
    RenderWidgetHostImpl* render_widget_host) {
  if (!delegate_ || (pointer_lock_widget_ != render_widget_host)) {
    return false;
  }
  return delegate_->IsWaitingForPointerLockPrompt(this);
}

void WebContentsImpl::LostPointerLock(
    RenderWidgetHostImpl* render_widget_host) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::LostPointerLock",
                        "render_widget_host", render_widget_host);
  CHECK(pointer_lock_widget_);

  if (WebContentsImpl::FromRenderWidgetHostImpl(pointer_lock_widget_) != this) {
    return pointer_lock_widget_->delegate()->LostPointerLock(
        render_widget_host);
  }

  pointer_lock_widget_->SendPointerLockLost();
  for (WebContentsImpl* current = this; current;
       current = current->GetOuterWebContents()) {
    current->pointer_lock_widget_ = nullptr;
  }

  if (delegate_) {
    delegate_->LostPointerLock();
  }
}

bool WebContentsImpl::HasPointerLock(RenderWidgetHostImpl* render_widget_host) {
  // To verify if the mouse is locked, the mouse_lock_widget_ needs to be
  // assigned to the widget that requested the mouse lock, and the top-level
  // platform RenderWidgetHostView needs to hold the mouse lock from the OS.
  auto* widget_host = GetTopLevelRenderWidgetHostView();
  return pointer_lock_widget_ == render_widget_host && widget_host &&
         widget_host->IsPointerLocked();
}

RenderWidgetHostImpl* WebContentsImpl::GetPointerLockWidget() {
  auto* widget_host = GetTopLevelRenderWidgetHostView();
  if (widget_host && widget_host->IsPointerLocked()) {
    return pointer_lock_widget_;
  }

  return nullptr;
}

bool WebContentsImpl::RequestKeyboardLock(
    RenderWidgetHostImpl* render_widget_host,
    bool esc_key_locked) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::RequestKeyboardLock",
                        "render_widget_host", render_widget_host,
                        "esc_key_locked", esc_key_locked);
  DCHECK(render_widget_host);
  if (WebContentsImpl::FromRenderWidgetHostImpl(render_widget_host) != this) {
    NOTREACHED();
  }

  // KeyboardLock is only supported when called by the top-level browsing
  // context and is not supported in embedded content scenarios.
  if (GetOuterWebContents()) {
    render_widget_host->GotResponseToKeyboardLockRequest(false);
    return false;
  }

  esc_key_locked_ = esc_key_locked;
  keyboard_lock_widget_ = render_widget_host;

  if (delegate_) {
    observers_.NotifyObservers(&WebContentsObserver::KeyboardLockRequested);
    delegate_->RequestKeyboardLock(this, esc_key_locked_);
  }
  return true;
}

void WebContentsImpl::CancelKeyboardLock(
    RenderWidgetHostImpl* render_widget_host) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::CancelKeyboardLockRequest",
                        "render_widget_host", render_widget_host);
  if (!keyboard_lock_widget_ || render_widget_host != keyboard_lock_widget_) {
    return;
  }

  RenderWidgetHostImpl* old_keyboard_lock_widget = keyboard_lock_widget_;
  keyboard_lock_widget_ = nullptr;

  if (delegate_) {
    delegate_->CancelKeyboardLockRequest(this);
  }

  old_keyboard_lock_widget->CancelKeyboardLock();
}

RenderWidgetHostImpl* WebContentsImpl::GetKeyboardLockWidget() {
  return keyboard_lock_widget_;
}

bool WebContentsImpl::OnRenderFrameProxyVisibilityChanged(
    RenderFrameProxyHost* render_frame_proxy_host,
    blink::mojom::FrameVisibility visibility) {
  OPTIONAL_TRACE_EVENT1("content",
                        "WebContentsImpl::OnRenderFrameProxyVisibilityChanged",
                        "visibility", static_cast<int>(visibility));

  // Check that we are responsible for the RenderFrameProxyHost by checking that
  // its FrameTreeNode matches our `primary_frame_tree_` root. Otherwise this is
  // not a visibility change that affects all frames in an inner WebContents.
  if (render_frame_proxy_host->frame_tree_node() !=
      primary_frame_tree_.root()) {
    return false;
  }

  // Not reachable with MPArch based guests.
  CHECK(!base::FeatureList::IsEnabled(features::kGuestViewMPArch));

  DCHECK(GetOuterWebContents());

  switch (visibility) {
    case blink::mojom::FrameVisibility::kRenderedInViewport:
      WasShown();
      break;
    case blink::mojom::FrameVisibility::kNotRendered:
      WasHidden();
      break;
    case blink::mojom::FrameVisibility::kRenderedOutOfViewport:
      WasOccluded();
      break;
  }
  return true;
}

FrameTree* WebContentsImpl::CreateNewWindow(
    RenderFrameHostImpl* opener,
    const mojom::CreateNewWindowParams& params,
    bool is_new_browsing_instance,
    bool has_user_gesture,
    SessionStorageNamespace* session_storage_namespace) {
  TRACE_EVENT2("browser,content,navigation", "WebContentsImpl::CreateNewWindow",
               "opener", opener, "params", params);
  DCHECK(opener);

  if (active_file_chooser_) {
    // Do not allow opening a new window or tab while a file select is active
    // file chooser to avoid user confusion over which tab triggered the file
    // chooser.
    opener->AddMessageToConsole(
        blink::mojom::ConsoleMessageLevel::kWarning,
        "window.open blocked due to active file chooser.");
    return nullptr;
  }

  int render_process_id = opener->GetProcess()->GetDeprecatedID();
  SiteInstanceImpl* source_site_instance = opener->GetSiteInstance();
  const auto& partition_config =
      source_site_instance->GetStoragePartitionConfig();

  {
    StoragePartition* partition =
        GetBrowserContext()->GetStoragePartition(source_site_instance);
    DOMStorageContextWrapper* dom_storage_context =
        static_cast<DOMStorageContextWrapper*>(
            partition->GetDOMStorageContext());
    SessionStorageNamespaceImpl* session_storage_namespace_impl =
        static_cast<SessionStorageNamespaceImpl*>(session_storage_namespace);
    CHECK(session_storage_namespace_impl->IsFromContext(dom_storage_context));
  }

  // TODO(crbug.com/40202416): Support a way for MPArch guests to support this.
  if (delegate_ &&
      delegate_->IsWebContentsCreationOverridden(
          opener, source_site_instance, params.window_container_type,
          opener->GetLastCommittedURL(), params.frame_name,
          params.target_url)) {
    auto* web_contents_impl =
        static_cast<WebContentsImpl*>(delegate_->CreateCustomWebContents(
            opener, source_site_instance, is_new_browsing_instance,
            opener->GetLastCommittedURL(), params.frame_name, params.target_url,
            partition_config, session_storage_namespace));
    if (!web_contents_impl) {
      return nullptr;
    }
    web_contents_impl->is_popup_ =
        params.disposition == WindowOpenDisposition::NEW_POPUP;
    SetPartitionedPopinOpenerOnNewWindowIfNeeded(web_contents_impl, params,
                                                 opener);
    return &web_contents_impl->GetPrimaryFrameTree();
  }

  bool renderer_started_hidden =
      params.disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB;

  bool is_guest =
      base::FeatureList::IsEnabled(features::kGuestViewMPArch)
          ? opener->GetOutermostMainFrame()->frame_tree()->is_guest()
          : IsGuest();
  // While some guest types do not have a guest SiteInstance, the ones that
  // don't all override WebContents creation above.
  CHECK_EQ(source_site_instance->IsGuest(), is_guest);

  // We usually create the new window in the same BrowsingInstance (group of
  // script-related windows), by passing in the current SiteInstance.  However,
  // if the opener is being suppressed, we need to ensure that the new
  // SiteInstance is created in a new BrowsingInstance.
  scoped_refptr<SiteInstance> site_instance;
  if (params.opener_suppressed) {
    if (is_guest) {
      // For guests, noopener windows can be created in a new BrowsingInstance
      // as long as they preserve the guest's StoragePartition.
      site_instance =
          SiteInstance::CreateForGuest(GetBrowserContext(), partition_config);
    } else {
      site_instance = SiteInstance::Create(GetBrowserContext());
    }
  } else {
    site_instance = source_site_instance;
  }

  if (is_guest && base::FeatureList::IsEnabled(features::kGuestViewMPArch)) {
    if (auto* guest = GuestPageHolderImpl::FromRenderFrameHost(*opener)) {
      return guest->CreateNewWindow(
          params.disposition, params.target_url, params.frame_name,
          std::move(site_instance),
          !params.opener_suppressed ? opener : nullptr);
    }
    return nullptr;
  }

  // Create the new web contents. This will automatically create the new
  // WebContentsView. In the future, we may want to create the view separately.
  CreateParams create_params(GetBrowserContext(), site_instance.get());
  create_params.main_frame_name = params.frame_name;
  create_params.opener_render_process_id = render_process_id;
  create_params.opener_render_frame_id = opener->GetRoutingID();
  create_params.opener_suppressed = params.opener_suppressed;
  create_params.initially_hidden = renderer_started_hidden;
  create_params.initial_popup_url = params.target_url;

  // Even though all codepaths leading here are in response to a renderer
  // trying to open a new window, if the new window ends up in a different
  // browsing instance, then the RenderViewHost, RenderWidgetHost,
  // RenderFrameHost constellation is effectively browser initiated
  // the opener's process will not given the routing IDs for the new
  // objects.
  create_params.renderer_initiated_creation = !is_new_browsing_instance;

  if (params.pip_options) {
    create_params.picture_in_picture_options = *(params.pip_options);
  }

  // Check whether there is an available prerendered page for this navigation if
  // this is not for guest. If it exists, take WebContents pre-created for
  // hosting the prerendered page instead of creating new WebContents.
  // TODO(crbug.com/40234240): Instead of filtering out the guest case here,
  // check it and drop prerender requests before starting prerendering.
  std::unique_ptr<WebContentsImpl> new_contents;
  if (!is_guest) {
    new_contents =
        GetPrerenderHostRegistry()->TakePreCreatedWebContentsForNewTabIfExists(
            params, create_params);
    if (new_contents) {
      // The SiteInstance of the pre-created WebContents should be in a
      // different BrowsingInstance from the source SiteInstance, while they
      // should be in the same StoragePartition.
      SiteInstanceImpl* new_site_instance = new_contents->GetSiteInstance();
      DCHECK(!new_site_instance->IsRelatedSiteInstance(source_site_instance));
      DCHECK_EQ(new_site_instance->GetStoragePartitionConfig(),
                source_site_instance->GetStoragePartitionConfig());
    }
  }

  if (!new_contents) {
    if (!is_guest) {
      create_params.context = view_->GetNativeView();
      new_contents = WebContentsImpl::Create(create_params);
    } else {
      new_contents =
          GetBrowserPluginGuest()->CreateNewGuestWindow(create_params);
    }
    new_contents->GetController().SetSessionStorageNamespace(
        partition_config, session_storage_namespace);
  }

  auto* new_contents_impl = new_contents.get();
  new_contents_impl->is_popup_ =
      params.disposition == WindowOpenDisposition::NEW_POPUP;
  SetPartitionedPopinOpenerOnNewWindowIfNeeded(new_contents_impl, params,
                                               opener);

  // Sets the newly created WebContents WindowOpenDisposition.
  new_contents_impl->original_window_open_disposition_ = params.disposition;

  // If the new frame has a name, make sure any SiteInstances that can find
  // this named frame have proxies for it.  Must be called after
  // SetSessionStorageNamespace, since this calls CreateRenderView, which uses
  // GetSessionStorageNamespace.
  if (!params.frame_name.empty()) {
    new_contents_impl->GetRenderManager()->CreateProxiesForNewNamedFrame(
        new_contents_impl->GetPrimaryMainFrame()->browsing_context_state());
  }

  // Save the window for later if we're not suppressing the opener (since it
  // will be shown immediately).
  if (!params.opener_suppressed) {
    if (!is_guest) {
      WebContentsView* new_view = new_contents_impl->view_.get();

      // TODO(brettw): It seems bogus that we have to call this function on the
      // newly created object and give it one of its own member variables.
      RenderWidgetHostView* widget_view = new_view->CreateViewForWidget(
          new_contents_impl->GetRenderViewHost()->GetWidget());
      view_->SetOverscrollControllerEnabled(CanOverscrollContent());
      if (!renderer_started_hidden) {
        // RenderWidgets for frames always initialize as hidden. If the renderer
        // created this window as visible, then we show it here.
        widget_view->Show();
      }
    }
    // Save the created window associated with the route so we can show it
    // later.
    //
    // TODO(ajwong): This should be keyed off the RenderFrame routing id or the
    // FrameTreeNode id instead of the routing id of the Widget for the main
    // frame.  https://crbug.com/545684
    int32_t main_frame_routing_id = new_contents_impl->GetPrimaryMainFrame()
                                        ->GetRenderWidgetHost()
                                        ->GetRoutingID();
    GlobalRoutingID id(render_process_id, main_frame_routing_id);
    pending_contents_[id] =
        CreatedWindow(std::move(new_contents), params.target_url);
    AddWebContentsDestructionObserver(new_contents_impl);
  }

  if (delegate_) {
    delegate_->WebContentsCreated(this, render_process_id,
                                  opener->GetRoutingID(), params.frame_name,
                                  params.target_url, new_contents_impl);
  }

  observers_.NotifyObservers(&WebContentsObserver::DidOpenRequestedURL,
                             new_contents_impl, opener, params.target_url,
                             params.referrer.To<Referrer>(), params.disposition,
                             ui::PAGE_TRANSITION_LINK,
                             false,  // started_from_context_menu
                             true);  // renderer_initiated

  if (!params.opener_suppressed) {
    return &new_contents_impl->GetPrimaryFrameTree();
  }

  // When the opener is suppressed, the original renderer cannot access the
  // new window.  As a result, we need to show and navigate the window here.
  bool was_blocked = false;
  base::WeakPtr<WebContentsImpl> weak_new_contents =
      new_contents_impl->weak_factory_.GetWeakPtr();
  WebContentsImpl* contents_to_load = new_contents_impl;
  if (delegate_) {
    WebContents* web_contents_navigated = delegate_->AddNewContents(
        this, std::move(new_contents), params.target_url, params.disposition,
        *params.features, has_user_gesture, &was_blocked);

    if (base::FeatureList::IsEnabled(features::kPwaNavigationCapturing)) {
      // The delegate may delete |new_contents_impl| during AddNewContents().
      // If that occurs and there isn't a replacement contents returned, exit.
      // Otherwise, use the replacement web contents that was navigated in.
      if (web_contents_navigated != nullptr && weak_new_contents) {
        CHECK(web_contents_navigated == weak_new_contents.get());
      }

      if (!weak_new_contents) {
        if (web_contents_navigated == nullptr) {
          return nullptr;
        }
        contents_to_load =
            static_cast<WebContentsImpl*>(web_contents_navigated);
      }
    } else if (!weak_new_contents) {
      return nullptr;
    }
  }

  if (!was_blocked) {
    std::unique_ptr<NavigationController::LoadURLParams> load_params =
        std::make_unique<NavigationController::LoadURLParams>(
            params.target_url);
    load_params->initiator_origin = opener->GetLastCommittedOrigin();
    load_params->initiator_process_id = opener->GetProcess()->GetDeprecatedID();
    load_params->initiator_frame_token = opener->GetFrameToken();
    // Avoiding setting |load_params->source_site_instance| when
    // |opener_suppressed| is true, because in that case we do not want to use
    // the old SiteInstance and/or BrowsingInstance.  See also the test here:
    // NewPopupCOOP_SameOriginPolicyAndCrossOriginIframeSetsNoopener.
    load_params->referrer = params.referrer.To<Referrer>();
    load_params->transition_type = ui::PAGE_TRANSITION_LINK;
    load_params->is_renderer_initiated = true;
    load_params->was_opener_suppressed = true;
    load_params->has_user_gesture = has_user_gesture;
    load_params->is_form_submission = params.is_form_submission;
    if (params.form_submission_post_data) {
      load_params->load_type = NavigationController::LOAD_TYPE_HTTP_POST;
      load_params->post_data = params.form_submission_post_data;
      load_params->post_content_type = params.form_submission_post_content_type;
    }
    load_params->impression = params.impression;
    load_params->override_user_agent =
        contents_to_load->should_override_user_agent_in_new_tabs_
            ? NavigationController::UA_OVERRIDE_TRUE
            : NavigationController::UA_OVERRIDE_FALSE;
    load_params->download_policy = params.download_policy;
    load_params->initiator_activation_and_ad_status =
        params.initiator_activation_and_ad_status;

    if (delegate_ && !is_guest &&
        !delegate_->ShouldResumeRequestsForCreatedWindow()) {
      // We are in asynchronous add new contents path, delay navigation.
      DCHECK(!contents_to_load->delayed_open_url_params_);
      contents_to_load->delayed_load_url_params_ = std::move(load_params);
    } else {
      contents_to_load->GetController().LoadURLWithParams(*load_params.get());
      if (!is_guest) {
        contents_to_load->Focus();
      }
    }
  }

  if (weak_new_contents) {
    return &new_contents_impl->GetPrimaryFrameTree();
  }
  return nullptr;
}

RenderWidgetHostImpl* WebContentsImpl::CreateNewPopupWidget(
    base::SafeRef<SiteInstanceGroup> site_instance_group,
    int32_t route_id,
    mojo::PendingAssociatedReceiver<blink::mojom::PopupWidgetHost>
        blink_popup_widget_host,
    mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost> blink_widget_host,
    mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::CreateNewPopupWidget",
                        "route_id", route_id);

  if (visibility_ != Visibility::VISIBLE) {
    // Don't create popups for hidden tabs. http://crbug.com/1521345
    return nullptr;
  }

  RenderWidgetHostImpl* widget_host = RenderWidgetHostFactory::CreateSelfOwned(
      &primary_frame_tree_, this, site_instance_group, route_id, IsHidden());

  widget_host->BindWidgetInterfaces(std::move(blink_widget_host),
                                    std::move(blink_widget));
  widget_host->BindPopupWidgetInterface(std::move(blink_popup_widget_host));
  RenderWidgetHostViewBase* widget_view =
      static_cast<RenderWidgetHostViewBase*>(
          view_->CreateViewForChildWidget(widget_host));
  if (!widget_view) {
    return nullptr;
  }
  widget_view->SetWidgetType(WidgetType::kPopup);

  // Save the created widget associated with the route so we can show it later.
  pending_widgets_.insert(
      {GlobalRoutingID(site_instance_group->process()->GetDeprecatedID(),
                       route_id),
       widget_host});
  AddRenderWidgetHostDestructionObserver(widget_host);

  return widget_host;
}

int64_t WebContentsImpl::AdjustWindowRect(gfx::Rect* bounds,
                                          RenderFrameHostImpl* opener) {
  // Auto-resize can override other mechanisms for enforcing min/max window size
  // for some modals and popups to fit the size of their contents. Borderless
  // apps shouldn't have overlap with auto-resize mode windows.
  if (!(GetRenderWidgetHostView() &&
        static_cast<RenderWidgetHostViewBase*>(GetRenderWidgetHostView())
            ->IsAutoResizeEnabled())) {
    // For borderless apps the minimum size is
    // `blink::kMinimumBorderlessWindowSize` instead of the default
    // `blink::kMinimumWindowSize`.
    int minimum_size =
        GetDisplayMode() == blink::mojom::DisplayMode::kBorderless &&
                IsWindowManagementGranted(opener)
            ? blink::kMinimumBorderlessWindowSize
            : blink::kMinimumWindowSize;
    AdjustWindowRectForMinimum(bounds, minimum_size);
  }

  int64_t display_id = display::kInvalidDisplayId;
  if (*bounds != gfx::Rect()) {
    display_id = AdjustWindowRectForDisplay(bounds, opener);
  }
  return display_id;
}

WebContents* WebContentsImpl::ShowCreatedWindow(
    RenderFrameHostImpl* opener,
    int main_frame_widget_route_id,
    WindowOpenDisposition disposition,
    const blink::mojom::WindowFeatures& window_features,
    bool user_gesture) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::ShowCreatedWindow",
                        "opener", opener, "main_frame_widget_route_id",
                        main_frame_widget_route_id);

  if (GuestPageHolderImpl::FromRenderFrameHost(*opener)) {
    // opened from a guest with MPArch, we don't need to do anything.
    return nullptr;
  }

  // This method is the renderer requesting an existing top level window to
  // show a new top level window that the renderer created. Each top level
  // window is associated with a WebContents. In this case it was created
  // earlier but showing it was deferred until the renderer requested for it
  // to be shown. We find that previously created WebContents here.
  // TODO(danakj): Why do we defer this show step until the renderer asks for it
  // when it will always do so. What needs to happen in the renderer before we
  // reach here?
  std::optional<CreatedWindow> owned_created = GetCreatedWindow(
      opener->GetProcess()->GetDeprecatedID(), main_frame_widget_route_id);

  // The browser may have rejected the request to make a new window, or the
  // renderer could be requesting to show a previously shown window (occurs when
  // mojom::CreateNewWindowStatus::kReuse is used). Ignore the request then.
  if (!owned_created || !owned_created->contents) {
    return nullptr;
  }

  if (active_file_chooser_) {
    // Do not allow opening a new window or tab while a file select is active
    // file chooser to avoid user confusion over which tab triggered the file
    // chooser.
    opener->AddMessageToConsole(
        blink::mojom::ConsoleMessageLevel::kWarning,
        "window.open blocked due to active file chooser.");
    return nullptr;
  }

  WebContentsImpl* created = owned_created->contents.get();

  // This uses the delegate for the WebContents where the window was created
  // from, to control how to show the newly created window.
  WebContentsDelegate* delegate = GetDelegate();

  // Individual members of |window_features.bounds| may be 0 to indicate that
  // the window.open() feature string did not specify a value. This code does
  // not distinguish between an unspecified value and 0.
  // Assume that if any single value is non-zero, all values should be used.
  // TODO(crbug.com/40092782): Utilize window_features.has_x and others.
  blink::mojom::WindowFeatures adjusted_features = window_features;
  int64_t display_id = AdjustWindowRect(&adjusted_features.bounds, opener);

  // Drop fullscreen when opening a WebContents to prohibit deceptive behavior.
  // Only drop fullscreen on the specific destination display, if it is known.
  // This supports sites using cross-screen window management capabilities to
  // retain fullscreen and open a window on another screen.
  ForSecurityDropFullscreen(display_id).RunAndReset();

  // The delegate can be null in tests.
  if (!delegate) {
    return nullptr;
  }

  // Mark the web contents as pending resume, then immediately do the resume if
  // the delegate wants it.
  created->is_resume_pending_ = true;
  if (delegate->ShouldResumeRequestsForCreatedWindow()) {
    created->ResumeLoadingCreatedWebContents();
  }

  return delegate->AddNewContents(this, std::move(owned_created->contents),
                                  std::move(owned_created->target_url),
                                  disposition, adjusted_features, user_gesture,
                                  nullptr);
}

void WebContentsImpl::ShowCreatedWidget(int process_id,
                                        int widget_route_id,
                                        const gfx::Rect& initial_rect,
                                        const gfx::Rect& initial_anchor_rect) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::ShowCreatedWidget",
                        "process_id", process_id, "widget_route_id",
                        widget_route_id);
  RenderWidgetHostViewBase* widget_host_view =
      static_cast<RenderWidgetHostViewBase*>(
          GetCreatedWidget(process_id, widget_route_id));
  if (!widget_host_view) {
    return;
  }

  // GetOutermostWebContents() returns |this| if there are no outer WebContents.
  auto* outer_web_contents = GetOuterWebContents();
  auto* outermost_web_contents = GetOutermostWebContents();
  RenderWidgetHostView* view =
      outermost_web_contents->GetRenderWidgetHostView();
  // It's not entirely obvious why we need the transform only in the case where
  // the outer webcontents is not the same as the outermost webcontents. It may
  // be due to the fact that oopifs that are children of the mainframe get
  // correct values for their screenrects, but deeper cross-process frames do
  // not. Hopefully this can be resolved with https://crbug.com/928825.
  // Handling these cases separately is needed for http://crbug.com/1015298.
  bool needs_transform = this != outermost_web_contents &&
                         outermost_web_contents != outer_web_contents;

  gfx::Rect transformed_rect(initial_rect);
  gfx::Rect transformed_anchor_rect(initial_anchor_rect);
  RenderWidgetHostView* this_view = GetRenderWidgetHostView();
  if (needs_transform) {
    // We need to transform the coordinates of initial_rect.
    gfx::Point origin =
        this_view->TransformPointToRootCoordSpace(initial_rect.origin());
    gfx::Point bottom_right =
        this_view->TransformPointToRootCoordSpace(initial_rect.bottom_right());
    transformed_rect =
        gfx::Rect(origin.x(), origin.y(), bottom_right.x() - origin.x(),
                  bottom_right.y() - origin.y());

    origin =
        this_view->TransformPointToRootCoordSpace(initial_anchor_rect.origin());
    bottom_right = this_view->TransformPointToRootCoordSpace(
        initial_anchor_rect.bottom_right());
    transformed_anchor_rect =
        gfx::Rect(origin.x(), origin.y(), bottom_right.x() - origin.x(),
                  bottom_right.y() - origin.y());
  }

  RenderWidgetHostImpl* render_widget_host_impl = widget_host_view->host();
  auto permission_exclusion_area_bounds =
      PermissionControllerImpl::FromBrowserContext(GetBrowserContext())
          ->GetExclusionAreaBoundsInScreen(outermost_web_contents);
  if (permission_exclusion_area_bounds &&
      permission_exclusion_area_bounds->Intersects(transformed_rect)) {
    render_widget_host_impl->ShutdownAndDestroyWidget(true);
    return;
  }

  widget_host_view->InitAsPopup(view, transformed_rect,
                                transformed_anchor_rect);

  // Renderer-owned popup widgets wait for the renderer to request for them
  // to be shown. We signal that this condition is satisfied by calling Init().
  render_widget_host_impl->Init();
}

std::optional<CreatedWindow> WebContentsImpl::GetCreatedWindow(
    int process_id,
    int main_frame_widget_route_id) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::GetCreatedWindow",
                        "process_id", process_id, "main_frame_widget_route_id",
                        main_frame_widget_route_id);

  auto key = GlobalRoutingID(process_id, main_frame_widget_route_id);
  auto iter = pending_contents_.find(key);

  // Certain systems can block the creation of new windows. If we didn't succeed
  // in creating one, just return NULL.
  if (iter == pending_contents_.end()) {
    return std::nullopt;
  }

  CreatedWindow result = std::move(iter->second);
  WebContentsImpl* new_contents = result.contents.get();
  pending_contents_.erase(key);
  RemoveWebContentsDestructionObserver(new_contents);

  // Don't initialize the guest WebContents immediately.
  if (new_contents->IsGuest()) {
    return result;
  }

  if (!new_contents->GetPrimaryMainFrame()
           ->GetProcess()
           ->IsInitializedAndNotDead() ||
      !new_contents->GetPrimaryMainFrame()->GetView()) {
    return std::nullopt;
  }

  return result;
}

RenderWidgetHostView* WebContentsImpl::GetCreatedWidget(int process_id,
                                                        int route_id) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::GetCreatedWidget",
                        "process_id", process_id, "route_id", route_id);

  auto iter = pending_widgets_.find(GlobalRoutingID(process_id, route_id));
  if (iter == pending_widgets_.end()) {
    DCHECK(false);
    return nullptr;
  }

  RenderWidgetHost* widget_host = iter->second;
  pending_widgets_.erase(GlobalRoutingID(process_id, route_id));
  RemoveRenderWidgetHostDestructionObserver(widget_host);

  if (!widget_host->GetProcess()->IsInitializedAndNotDead()) {
    // The view has gone away or the renderer crashed. Nothing to do.
    return nullptr;
  }

  return widget_host->GetView();
}

void WebContentsImpl::CreateMediaPlayerHostForRenderFrameHost(
    RenderFrameHostImpl* frame_host,
    mojo::PendingAssociatedReceiver<media::mojom::MediaPlayerHost> receiver) {
  media_web_contents_observer()->BindMediaPlayerHost(frame_host->GetGlobalId(),
                                                     std::move(receiver));
}

void WebContentsImpl::RequestMediaAccessPermission(
    RenderFrameHostImpl* render_frame_host,
    const MediaStreamRequest& request,
    MediaResponseCallback callback) {
  OPTIONAL_TRACE_EVENT2("content",
                        "WebContentsImpl::RequestMediaAccessPermission",
                        "render_process_id", request.render_process_id,
                        "render_frame_id", request.render_frame_id);

  if (GuestPageHolderImpl* guest =
          render_frame_host
              ? GuestPageHolderImpl::FromRenderFrameHost(*render_frame_host)
              : nullptr) {
    if (auto* delegate = guest->delegate()) {
      delegate->GuestRequestMediaAccessPermission(request, std::move(callback));
      return;
    }
  } else if (delegate_) {
    delegate_->RequestMediaAccessPermission(this, request, std::move(callback));
    return;
  }
  std::move(callback).Run(
      blink::mojom::StreamDevicesSet(),
      blink::mojom::MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN,
      std::unique_ptr<MediaStreamUI>());
}

void WebContentsImpl::ProcessSelectAudioOutput(
    const SelectAudioOutputRequest& request,
    SelectAudioOutputCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (delegate_) {
    delegate_->ProcessSelectAudioOutput(request, std::move(callback));
  } else {
    std::move(callback).Run(
        base::unexpected(content::SelectAudioOutputError::kNotSupported));
  }
}

bool WebContentsImpl::CheckMediaAccessPermission(
    RenderFrameHostImpl* render_frame_host,
    const url::Origin& security_origin,
    blink::mojom::MediaStreamType type) {
  OPTIONAL_TRACE_EVENT2("content",
                        "WebContentsImpl::CheckMediaAccessPermission",
                        "render_frame_host", render_frame_host,
                        "security_origin", security_origin);

  DCHECK(type == blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE ||
         type == blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE);

  if (auto* guest =
          GuestPageHolderImpl::FromRenderFrameHost(*render_frame_host)) {
    if (auto* delegate = guest->delegate()) {
      return delegate->GuestCheckMediaAccessPermission(render_frame_host,
                                                       security_origin, type);
    }
    return false;
  }
  return delegate_ && delegate_->CheckMediaAccessPermission(
                          render_frame_host, security_origin, type);
}

void WebContentsImpl::SetCaptureHandleConfig(
    blink::mojom::CaptureHandleConfigPtr config) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (capture_handle_config_ == *config) {
    return;  // Avoid unnecessary notifications.
  }

  capture_handle_config_ = std::move(*config);

  // Propagates the capture-handle-config inside of the browser process.
  // Only render processes which are eligible based on |permittedOrigins|
  // will get this.
  observers_.NotifyObservers(&WebContentsObserver::OnCaptureHandleConfigUpdate,
                             capture_handle_config_);
}

bool WebContentsImpl::IsJavaScriptDialogShowing() const {
  return is_showing_javascript_dialog_;
}

bool WebContentsImpl::ShouldIgnoreUnresponsiveRenderer() {
  // Suppress unresponsive renderers if the command line asks for it.
  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
          input::switches::kDisableHangMonitor) ||
      !base::FeatureList::IsEnabled(input::features::kRendererHangWatcher)) {
    return true;
  }

  if (IsBeingDestroyed()) {
    return true;
  }

  if (suppress_unresponsive_renderer_count_ > 0) {
    return true;
  }

  // Ignore unresponsive renderers if the debugger is attached to them since the
  // unresponsiveness might be a result of the renderer sitting on a breakpoint.
  //
#if BUILDFLAG(IS_WIN)
  // Check if a windows debugger is attached to the renderer process.
  base::ProcessHandle process_handle =
      GetPrimaryMainFrame()->GetProcess()->GetProcess().Handle();
  BOOL debugger_present = FALSE;
  if (CheckRemoteDebuggerPresent(process_handle, &debugger_present) &&
      debugger_present) {
    return true;
  }
#endif  // BUILDFLAG(IS_WIN)

  // TODO(pfeldman): Fix this to only return true if the renderer is *actually*
  // sitting on a breakpoint. https://crbug.com/684202
  return DevToolsAgentHost::IsDebuggerAttached(this);
}

ui::AXMode WebContentsImpl::GetAccessibilityMode() {
  return accessibility_mode_;
}

void WebContentsImpl::AXTreeIDForMainFrameHasChanged() {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::AXTreeIDForMainFrameHasChanged");

  RenderWidgetHostViewBase* rwhv =
      static_cast<RenderWidgetHostViewBase*>(GetRenderWidgetHostView());
  if (rwhv) {
    rwhv->SetMainFrameAXTreeID(GetPrimaryMainFrame()->GetAXTreeID());
  }

  observers_.NotifyObservers(
      &WebContentsObserver::AXTreeIDForMainFrameHasChanged);
}

void WebContentsImpl::ProcessAccessibilityUpdatesAndEvents(
    ui::AXUpdatesAndEvents& details) {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::AccessibilityEventReceived");

  // First, supply the data to consumers that won't change it.
  observers_.NotifyObservers(&WebContentsObserver::AccessibilityEventReceived,
                             details);

  // Next, supply the data to consumers that may change it or who need to avoid
  // extra copying. Note that this also includes those who will pass to mojo
  // pipes not taking const.
  // TODO(accessibility): add support for this. WebContentsDelegate isn't the
  // right abstraction since it contains many other side effects.
}

void WebContentsImpl::AccessibilityLocationChangesReceived(
    const ui::AXTreeID& tree_id,
    ui::AXLocationAndScrollUpdates& details) {
  OPTIONAL_TRACE_EVENT0(
      "content", "WebContentsImpl::AccessibilityLocationChangesReceived");
  observers_.NotifyObservers(
      &WebContentsObserver::AccessibilityLocationChangesReceived, tree_id,
      details);
}

ui::AXNode* WebContentsImpl::GetAccessibilityRootNode() {
  ui::BrowserAccessibilityManager* manager =
      GetRootBrowserAccessibilityManager();
  if (!manager || !manager->ax_tree()) {
    return nullptr;
  }
  return manager->ax_tree()->root();
}

std::string WebContentsImpl::DumpAccessibilityTree(
    bool internal,
    std::vector<ui::AXPropertyFilter> property_filters) {
  ui::AXApiType::Type api_type =
      internal ? ui::AXApiType::Type(ui::AXApiType::kBlink)
               : AXInspectFactory::DefaultPlatformFormatterType();
  return DumpAccessibilityTree(api_type, property_filters);
}

std::string WebContentsImpl::DumpAccessibilityTree(
    ui::AXApiType::Type api_type,
    std::vector<ui::AXPropertyFilter> property_filters) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::DumpAccessibilityTree");
  auto* ax_mgr = GetOrCreateRootBrowserAccessibilityManager();
  // Since for Web Content we get the AXTree updates through the renderer at a
  // point after the manager is created, there are cases where at this point in
  // the lifecycle the AXTree associated with `ax_mgr` does not have a valid
  // tree ID. As such, if this is the case we return an empty string early. If
  // we don't have this check, there will be a scenario where we then try to get
  // the manager using the ID (which at this point is invalid) which leads to a
  // crash. See https://crbug.com/1405036.
  if (!ax_mgr || !ax_mgr->HasValidTreeID()) {
    return "-";
  }

  // Developer mode: crash immediately on any accessibility fatal error.
  // This only runs during integration tests, or if a developer is
  // using an inspection tool, e.g. chrome://accessibility.
  ui::AXTreeManager::AlwaysFailFast();
  DCHECK(base::Contains(AXInspectFactory::SupportedApis(), api_type));
  std::unique_ptr<ui::AXTreeFormatter> formatter =
      AXInspectFactory::CreateFormatter(api_type);

  formatter->SetPropertyFilters(property_filters);
  return formatter->Format(ax_mgr->GetBrowserAccessibilityRoot());
}

void WebContentsImpl::RecordAccessibilityEvents(
    bool start_recording,
    std::optional<ui::AXEventCallback> callback) {
  RecordAccessibilityEvents(AXInspectFactory::DefaultPlatformRecorderType(),
                            start_recording, callback);
}
void WebContentsImpl::RecordAccessibilityEvents(
    ui::AXApiType::Type api_type,
    bool start_recording,
    std::optional<ui::AXEventCallback> callback) {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::RecordAccessibilityEvents");

  // Only pass a callback to RecordAccessibilityEvents when starting to record.
  DCHECK_EQ(start_recording, callback.has_value());
  if (start_recording) {
    // TODO(grt): Do we need to do the same for all inner WebContentses?.
    recording_mode_ =
        BrowserAccessibilityState::GetInstance()
            ->CreateScopedModeForWebContents(this, ui::kAXModeBasic);
    auto* ax_mgr = GetOrCreateRootBrowserAccessibilityManager();
    CHECK(ax_mgr);
    base::ProcessId pid = base::Process::Current().Pid();
    gfx::AcceleratedWidget widget =
        ax_mgr->GetBrowserAccessibilityRoot()
            ->GetTargetForNativeAccessibilityEvent();

    DCHECK(base::Contains(AXInspectFactory::SupportedApis(), api_type));
    event_recorder_ = content::AXInspectFactory::CreateRecorder(
        api_type, ax_mgr, pid, ui::AXTreeSelector(widget));
    event_recorder_->ListenToEvents(*callback);
  } else {
    if (event_recorder_) {
      event_recorder_->WaitForDoneRecording();
      event_recorder_.reset(nullptr);
    }
    recording_mode_.reset();
  }
}

void WebContentsImpl::UnrecoverableAccessibilityError() {
  SetAccessibilityMode(ui::AXMode::kNone);
  unrecoverable_accessibility_error_ = true;
}

device::mojom::GeolocationContext* WebContentsImpl::GetGeolocationContext() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::GetGeolocationContext");
  if (delegate_) {
    auto* installed_webapp_context =
        delegate_->GetInstalledWebappGeolocationContext();
    if (installed_webapp_context) {
      return installed_webapp_context;
    }
  }

  if (!geolocation_context_) {
    GetDeviceService().BindGeolocationContext(
        geolocation_context_.BindNewPipeAndPassReceiver());
  }
  return geolocation_context_.get();
}

device::mojom::WakeLockContext* WebContentsImpl::GetWakeLockContext() {
  if (!enable_wake_locks_) {
    return nullptr;
  }
  if (!wake_lock_context_host_) {
    wake_lock_context_host_ = std::make_unique<WakeLockContextHost>(this);
  }
  return wake_lock_context_host_->GetWakeLockContext();
}

#if BUILDFLAG(IS_ANDROID) || (BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_IOS_TVOS))
void WebContentsImpl::GetNFC(
    RenderFrameHostImpl* render_frame_host,
    mojo::PendingReceiver<device::mojom::NFC> receiver) {
  if (!nfc_host_) {
    nfc_host_ = std::make_unique<NFCHost>(this);
  }
  nfc_host_->GetNFC(render_frame_host, std::move(receiver));
}
#endif

void WebContentsImpl::SendScreenRects() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::SendScreenRects");

  DCHECK(!IsBeingDestroyed());

  GetPrimaryMainFrame()->ForEachRenderFrameHostImpl(
      [](RenderFrameHostImpl* render_frame_host) {
        if (render_frame_host->is_local_root()) {
          render_frame_host->GetRenderWidgetHost()->SendScreenRects();
        }
      });
}

void WebContentsImpl::SendActiveState(bool active) {
  DCHECK(!IsBeingDestroyed());

  // Replicate the active state to all LocalRoots.
  GetPrimaryMainFrame()->ForEachRenderFrameHostImpl(
      [active](RenderFrameHostImpl* render_frame_host) {
        if (render_frame_host->is_local_root()) {
          render_frame_host->GetRenderWidgetHost()->SetActive(active);
        }
      });
}

TextInputManager* WebContentsImpl::GetTextInputManager() {
  if (suppress_ime_events_for_testing_) {
    return nullptr;
  }

  if (GetOuterWebContents()) {
    return GetOuterWebContents()->GetTextInputManager();
  }

  if (!text_input_manager_ && !browser_plugin_guest_) {
    text_input_manager_ = std::make_unique<TextInputManager>();
  }

  return text_input_manager_.get();
}

bool WebContentsImpl::IsWidgetForPrimaryMainFrame(
    RenderWidgetHostImpl* render_widget_host) {
  return render_widget_host == GetPrimaryMainFrame()->GetRenderWidgetHost();
}

ui::BrowserAccessibilityManager*
WebContentsImpl::GetRootBrowserAccessibilityManager() {
  RenderFrameHostImpl* rfh =
      static_cast<RenderFrameHostImpl*>(GetPrimaryMainFrame());
  return rfh ? rfh->browser_accessibility_manager() : nullptr;
}

ui::BrowserAccessibilityManager*
WebContentsImpl::GetOrCreateRootBrowserAccessibilityManager() {
  RenderFrameHostImpl* rfh =
      static_cast<RenderFrameHostImpl*>(GetPrimaryMainFrame());
  return rfh ? rfh->GetOrCreateBrowserAccessibilityManager() : nullptr;
}

void WebContentsImpl::ExecuteEditCommand(
    const std::string& command,
    const std::optional<std::u16string>& value) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::ExecuteEditCommand");
  auto* input_handler = GetFocusedFrameWidgetInputHandler();
  if (!input_handler) {
    return;
  }

  input_handler->ExecuteEditCommand(command, value);
}

void WebContentsImpl::MoveRangeSelectionExtent(const gfx::Point& extent) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::MoveRangeSelectionExtent");
  auto* input_handler = GetFocusedFrameWidgetInputHandler();
  if (!input_handler) {
    return;
  }

  input_handler->MoveRangeSelectionExtent(extent);
}

void WebContentsImpl::SelectRange(const gfx::Point& base,
                                  const gfx::Point& extent) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::SelectRange");
  auto* input_handler = GetFocusedFrameWidgetInputHandler();
  if (!input_handler) {
    return;
  }

  input_handler->SelectRange(base, extent);
}

void WebContentsImpl::SelectAroundCaret(
    blink::mojom::SelectionGranularity granularity,
    bool should_show_handle,
    bool should_show_context_menu) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::SelectAroundCaret");
  auto* input_handler = GetFocusedFrameWidgetInputHandler();
  if (!input_handler) {
    return;
  }

  last_interaction_time_ = ui::EventTimeForNow();
  input_handler->SelectAroundCaret(granularity, should_show_handle,
                                   should_show_context_menu, base::DoNothing());
}

void WebContentsImpl::MoveCaret(const gfx::Point& extent) {
  OPTIONAL_TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("content.verbose"),
                        "WebContentsImpl::MoveCaret");
  auto* input_handler = GetFocusedFrameWidgetInputHandler();
  if (!input_handler) {
    return;
  }

  input_handler->MoveCaret(extent);
}

base::UnguessableToken WebContentsImpl::GetCompositorFrameSinkGroupingId()
    const {
  return compositor_frame_sink_grouping_id_;
}

void WebContentsImpl::AdjustSelectionByCharacterOffset(
    int start_adjust,
    int end_adjust,
    bool show_selection_menu) {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::AdjustSelectionByCharacterOffset");
  auto* input_handler = GetFocusedFrameWidgetInputHandler();
  if (!input_handler) {
    return;
  }

  using blink::mojom::SelectionMenuBehavior;
  input_handler->AdjustSelectionByCharacterOffset(
      start_adjust, end_adjust,
      show_selection_menu ? SelectionMenuBehavior::kShow
                          : SelectionMenuBehavior::kHide);
}

void WebContentsImpl::ResizeDueToAutoResize(
    RenderWidgetHostImpl* render_widget_host,
    const gfx::Size& new_size) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::ResizeDueToAutoResize",
                        "render_widget_host", render_widget_host);

  // If we are a guest frame tree and the RenderWidgetHost is the same as the
  // guest's main frame widget, then send the guest a notification about the
  // resize.
  if (render_widget_host->frame_tree()->is_guest() &&
      render_widget_host->frame_tree()->GetMainFrame()->GetRenderWidgetHost() ==
          render_widget_host) {
    if (auto* guest = GuestPageHolderImpl::FromRenderFrameHost(
            *render_widget_host->frame_tree()->GetMainFrame())) {
      guest->delegate()->GuestResizeDueToAutoResize(new_size);
    }
    return;
  }

  if (render_widget_host != GetRenderViewHost()->GetWidget()) {
    return;
  }

  if (delegate_) {
    delegate_->ResizeDueToAutoResize(this, new_size);
  }
}

WebContents* WebContentsImpl::OpenURL(
    const OpenURLParams& params,
    base::OnceCallback<void(content::NavigationHandle&)>
        navigation_handle_callback) {
  TRACE_EVENT1("content", "WebContentsImpl::OpenURL", "url", params.url);
#if DCHECK_IS_ON()
  DCHECK(params.Valid());
#endif

  if (!delegate_) {
    // Embedder can delay setting a delegate on new WebContents with
    // WebContentsDelegate::ShouldResumeRequestsForCreatedWindow. In the mean
    // time, navigations, including the initial one, that goes through OpenURL
    // should be delayed until embedder is ready to resume loading.
    delayed_open_url_params_ = std::make_unique<OpenURLParams>(params);
    delayed_navigation_handle_callback_ = std::move(navigation_handle_callback);

    // If there was a navigation deferred when creating the window through
    // CreateNewWindow, drop it in favor of this navigation.
    delayed_load_url_params_.reset();

    return nullptr;
  }

  RenderFrameHostImpl* source_render_frame_host =
      RenderFrameHostImpl::FromID(GlobalRenderFrameHostId(
          params.source_render_process_id, params.source_render_frame_id));

  // Prevent frames that are not active (e.g. a prerendering page) from opening
  // new windows, tabs, popups, etc.
  if (params.disposition != WindowOpenDisposition::CURRENT_TAB &&
      source_render_frame_host && !source_render_frame_host->IsActive()) {
    return nullptr;
  }

  if (params.frame_tree_node_id) {
    if (auto* frame_tree_node =
            FrameTreeNode::GloballyFindByID(params.frame_tree_node_id)) {
      // If a frame tree node ID is specified and it exists, ensure it is for a
      // node within this WebContents. Note: this WebContents could be hosting
      // multiple frame trees (e.g. prerendering) so it's not enough to check
      // against this->primary_frame_tree_. Check against page_delegate(), which
      // is always a WebContentsImpl, while delegate() may be implemented by
      // something else such as for prerendered frame trees.
      FrameTree& frame_tree = frame_tree_node->frame_tree();
      CHECK_EQ(frame_tree.page_delegate(), this);

      // Prerendering and fenced frame navigations are hidden from embedders.
      // If the navigation is targeting a frame in a prerendering or fenced
      // frame tree, we shouldn't run that navigation through the embedder
      // delegate. Embedder implementations of
      // `WebContentsDelegate::OpenURLFromTab` assume that the primary
      // frame tree Navigation controller should be used for navigating.
      // Instead, we just navigate directly on the relevant frame
      // tree.
      if (frame_tree.is_prerendering() ||
          frame_tree_node->IsInFencedFrameTree()) {
        DCHECK_EQ(params.disposition, WindowOpenDisposition::CURRENT_TAB);
        frame_tree.controller().LoadURLWithParams(
            NavigationController::LoadURLParams(params));
        return this;
      }
    } else {
      // If the node doesn't exist it was probably removed from its frame tree.
      // In that case, abort since continuing would navigate the root frame.
      return nullptr;
    }
  }

  if (source_render_frame_host &&
      base::FeatureList::IsEnabled(features::kGuestViewMPArch)) {
    if (auto* guest = GuestPageHolderImpl::FromRenderFrameHost(
            *source_render_frame_host)) {
      if (auto* delegate = guest->delegate()) {
        delegate->GuestOpenURL(params, std::move(navigation_handle_callback));
      }
      return nullptr;
    }
  }

  WebContents* new_contents = delegate_->OpenURLFromTab(
      this, params, std::move(navigation_handle_callback));

  if (source_render_frame_host && params.source_site_instance) {
    CHECK_EQ(source_render_frame_host->GetSiteInstance(),
             params.source_site_instance.get());
  }

  if (new_contents && source_render_frame_host && new_contents != this) {
    observers_.NotifyObservers(
        &WebContentsObserver::DidOpenRequestedURL, new_contents,
        source_render_frame_host, params.url, params.referrer,
        params.disposition, params.transition, params.started_from_context_menu,
        params.is_renderer_initiated);
  }

  return new_contents;
}

void WebContentsImpl::SetHistoryIndexAndLengthForView(
    RenderViewHost* render_view_host,
    int history_index,
    int history_length) {
  OPTIONAL_TRACE_EVENT2(
      "content", "WebContentsImpl::SetHistoryIndexAndLengthForView",
      "history_index", history_index, "history_length", history_length);
  if (auto& broadcast = static_cast<RenderViewHostImpl*>(render_view_host)
                            ->GetAssociatedPageBroadcast()) {
    broadcast->SetHistoryIndexAndLength(history_index, history_length);
  }
}

void WebContentsImpl::ReloadFocusedFrame() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::ReloadFocusedFrame");
  RenderFrameHost* focused_frame = GetFocusedFrame();
  if (!focused_frame) {
    return;
  }

  focused_frame->Reload();
}

void WebContentsImpl::Undo() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::Undo");
  auto* input_handler = GetFocusedFrameWidgetInputHandler();
  if (!input_handler) {
    return;
  }

  last_interaction_time_ = ui::EventTimeForNow();
  input_handler->Undo();
  RecordAction(base::UserMetricsAction("Undo"));
}

void WebContentsImpl::Redo() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::Redo");
  auto* input_handler = GetFocusedFrameWidgetInputHandler();
  if (!input_handler) {
    return;
  }

  last_interaction_time_ = ui::EventTimeForNow();
  input_handler->Redo();
  RecordAction(base::UserMetricsAction("Redo"));
}

void WebContentsImpl::Cut() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::Cut");
  auto* input_handler = GetFocusedFrameWidgetInputHandler();
  if (!input_handler) {
    return;
  }

  last_interaction_time_ = ui::EventTimeForNow();
  input_handler->Cut();
  RecordAction(base::UserMetricsAction("Cut"));
}

void WebContentsImpl::Copy() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::Copy");
  auto* input_handler = GetFocusedFrameWidgetInputHandler();
  if (!input_handler) {
    return;
  }

  last_interaction_time_ = ui::EventTimeForNow();
  input_handler->Copy();
  RecordAction(base::UserMetricsAction("Copy"));
}

void WebContentsImpl::CopyToFindPboard() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::CopyToFindPboard");
#if BUILDFLAG(IS_MAC)
  auto* input_handler = GetFocusedFrameWidgetInputHandler();
  if (!input_handler) {
    return;
  }

  last_interaction_time_ = ui::EventTimeForNow();
  // Windows/Linux don't have the concept of a find pasteboard.
  input_handler->CopyToFindPboard();
  RecordAction(base::UserMetricsAction("CopyToFindPboard"));
#endif
}

void WebContentsImpl::CenterSelection() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::CenterSelection");
#if BUILDFLAG(IS_MAC)
  auto* input_handler = GetFocusedFrameWidgetInputHandler();
  if (!input_handler) {
    return;
  }

  last_interaction_time_ = ui::EventTimeForNow();
  input_handler->CenterSelection();
#endif
}

void WebContentsImpl::Paste() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::Paste");
  auto* input_handler = GetFocusedFrameWidgetInputHandler();
  if (!input_handler) {
    return;
  }

  last_interaction_time_ = ui::EventTimeForNow();
  input_handler->Paste();
  observers_.NotifyObservers(&WebContentsObserver::OnPaste);
  RecordAction(base::UserMetricsAction("Paste"));
}

void WebContentsImpl::PasteAndMatchStyle() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::PasteAndMatchStyle");
  auto* input_handler = GetFocusedFrameWidgetInputHandler();
  if (!input_handler) {
    return;
  }

  last_interaction_time_ = ui::EventTimeForNow();
  input_handler->PasteAndMatchStyle();
  observers_.NotifyObservers(&WebContentsObserver::OnPaste);
  RecordAction(base::UserMetricsAction("PasteAndMatchStyle"));
}

void WebContentsImpl::Delete() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::Delete");
  auto* input_handler = GetFocusedFrameWidgetInputHandler();
  if (!input_handler) {
    return;
  }

  last_interaction_time_ = ui::EventTimeForNow();
  input_handler->Delete();
  RecordAction(base::UserMetricsAction("DeleteSelection"));
}

void WebContentsImpl::SelectAll() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::SelectAll");
  auto* input_handler = GetFocusedFrameWidgetInputHandler();
  if (!input_handler) {
    return;
  }

  last_interaction_time_ = ui::EventTimeForNow();
  input_handler->SelectAll();
  RecordAction(base::UserMetricsAction("SelectAll"));
}

void WebContentsImpl::CollapseSelection() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::CollapseSelection");
  auto* input_handler = GetFocusedFrameWidgetInputHandler();
  if (!input_handler) {
    return;
  }

  last_interaction_time_ = ui::EventTimeForNow();
  input_handler->CollapseSelection();
}

void WebContentsImpl::ScrollToTopOfDocument() {
  ExecuteEditCommand("ScrollToBeginningOfDocument", std::nullopt);
}

void WebContentsImpl::ScrollToBottomOfDocument() {
  ExecuteEditCommand("ScrollToEndOfDocument", std::nullopt);
}

void WebContentsImpl::Replace(const std::u16string& word) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::Replace");
  auto* input_handler = GetFocusedFrameWidgetInputHandler();
  if (!input_handler) {
    return;
  }

  last_interaction_time_ = ui::EventTimeForNow();
  input_handler->Replace(word);
}

void WebContentsImpl::ReplaceMisspelling(const std::u16string& word) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::ReplaceMisspelling");
  auto* input_handler = GetFocusedFrameWidgetInputHandler();
  if (!input_handler) {
    return;
  }

  last_interaction_time_ = ui::EventTimeForNow();
  input_handler->ReplaceMisspelling(word);
}

void WebContentsImpl::NotifyContextMenuClosed(
    const GURL& link_followed,
    const std::optional<blink::Impression>& impression) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::NotifyContextMenuClosed");
  RenderFrameHost* focused_frame = GetFocusedFrame();
  if (!focused_frame) {
    return;
  }

  if (context_menu_client_) {
    context_menu_client_->ContextMenuClosed(link_followed, impression);
  }

  context_menu_client_.reset();
}

void WebContentsImpl::ExecuteCustomContextMenuCommand(
    int action,
    const GURL& link_followed) {
  OPTIONAL_TRACE_EVENT1("content",
                        "WebContentsImpl::ExecuteCustomContextMenuCommand",
                        "action", action);
  RenderFrameHost* focused_frame = GetFocusedFrame();
  if (!focused_frame) {
    return;
  }

  if (context_menu_client_) {
    context_menu_client_->CustomContextMenuAction(action);
  }
}

gfx::NativeView WebContentsImpl::GetNativeView() {
  return view_->GetNativeView();
}

gfx::NativeView WebContentsImpl::GetContentNativeView() {
  return view_->GetContentNativeView();
}

gfx::NativeWindow WebContentsImpl::GetTopLevelNativeWindow() {
  return view_->GetTopLevelNativeWindow();
}

gfx::Rect WebContentsImpl::GetViewBounds() {
  return view_->GetViewBounds();
}

gfx::Rect WebContentsImpl::GetContainerBounds() {
  return view_->GetContainerBounds();
}

DropData* WebContentsImpl::GetDropData() {
  return view_->GetDropData();
}

void WebContentsImpl::Focus() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::Focus");
  view_->Focus();
}

void WebContentsImpl::SetInitialFocus() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::SetInitialFocus");
  view_->SetInitialFocus();
}

void WebContentsImpl::StoreFocus() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::StoreFocus");
  view_->StoreFocus();
}

void WebContentsImpl::RestoreFocus() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::RestoreFocus");
  view_->RestoreFocus();
}

void WebContentsImpl::FocusThroughTabTraversal(bool reverse) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::FocusThroughTabTraversal",
                        "reverse", reverse);
  view_->FocusThroughTabTraversal(reverse);
}

bool WebContentsImpl::IsSavable() {
  // WebKit creates Document object when MIME type is application/xhtml+xml,
  // so we also support this MIME type.
  std::string mime_type = GetContentsMimeType();
  return mime_type == "text/html" || mime_type == "text/xml" ||
         mime_type == "application/xhtml+xml" || mime_type == "text/plain" ||
         mime_type == "text/css" ||
         blink::IsSupportedJavascriptMimeType(mime_type);
}

void WebContentsImpl::OnSavePage() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::OnSavePage");
  // If we can not save the page, try to download it.
  if (!IsSavable()) {
    SaveFrame(GetLastCommittedURL(), Referrer(), GetPrimaryMainFrame());
    return;
  }

  Stop();

  // Create the save package and possibly prompt the user for the name to save
  // the page as. The user prompt is an asynchronous operation that runs on
  // another thread.
  save_package_ = new SavePackage(GetPrimaryPage());
  save_package_->GetSaveInfo();
}

// Used in automated testing to bypass prompting the user for file names.
// Instead, the names and paths are hard coded rather than running them through
// file name sanitation and extension / mime checking.
bool WebContentsImpl::SavePage(const base::FilePath& main_file,
                               const base::FilePath& dir_path,
                               SavePageType save_type) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::SavePage", "main_file",
                        main_file, "dir_path", dir_path);
  // Stop the page from navigating.
  Stop();

  save_package_ =
      new SavePackage(GetPrimaryPage(), save_type, main_file, dir_path);
  return save_package_->Init(SavePackageDownloadCreatedCallback());
}

void WebContentsImpl::SaveFrame(const GURL& url,
                                const Referrer& referrer,
                                RenderFrameHost* rfh) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::SaveFrame");
  SaveFrameWithHeaders(url, referrer, std::string(), std::u16string(), rfh,
                       /*is_subresource=*/false);
}

void WebContentsImpl::SaveFrameWithHeaders(
    const GURL& url,
    const Referrer& referrer,
    const std::string& headers,
    const std::u16string& suggested_filename,
    RenderFrameHost* rfh,
    bool is_subresource) {
  DCHECK(rfh);
  auto& rfhi = *static_cast<RenderFrameHostImpl*>(rfh);

  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::SaveFrameWithHeaders",
                        "url", url, "headers", headers);
  // Check and see if the guest can handle this.
  if (delegate_) {
    WebContents* guest_web_contents = nullptr;
    if (browser_plugin_embedder_) {
      BrowserPluginGuest* guest = browser_plugin_embedder_->GetFullPageGuest();
      if (guest) {
        guest_web_contents = guest->GetWebContents();
      }
    } else if (browser_plugin_guest_) {
      guest_web_contents = this;
    }

    if (guest_web_contents && delegate_->GuestSaveFrame(guest_web_contents)) {
      return;
    }
  }

  if (!GetLastCommittedURL().is_valid()) {
    return;
  }
  if (delegate_ && delegate_->SaveFrame(url, referrer, rfh)) {
    return;
  }

  int64_t post_id = -1;
  if (rfhi.is_main_frame() && !is_subresource) {
    NavigationEntry* entry =
        rfhi.frame_tree()->controller().GetLastCommittedEntry();
    if (entry) {
      post_id = entry->GetPostID();
    }
  }
  net::NetworkTrafficAnnotationTag traffic_annotation =
      net::DefineNetworkTrafficAnnotation("download_web_contents_frame", R"(
        semantics {
          sender: "Save Page Action"
          description:
            "Saves the given frame's URL to the local file system."
          trigger:
            "The user has triggered a save operation on the frame through a "
            "context menu or other mechanism."
          data: "None."
          destination: WEBSITE
        }
        policy {
          cookies_allowed: YES
          cookies_store: "user"
          setting:
            "This feature cannot be disabled by settings, but it's is only "
            "triggered by user request."
          policy_exception_justification: "Not implemented."
        })");
  auto params = std::make_unique<download::DownloadUrlParameters>(
      url, rfh->GetProcess()->GetDeprecatedID(), rfh->GetRoutingID(),
      traffic_annotation);
  params->set_referrer(referrer.url);
  params->set_referrer_policy(
      Referrer::ReferrerPolicyForUrlRequest(referrer.policy));
  params->set_post_id(post_id);
  if (post_id >= 0) {
    params->set_method("POST");
  }
  params->set_prompt(true);

  if (!headers.empty()) {
    for (download::DownloadUrlParameters::RequestHeadersNameValuePair
             key_value : ParseDownloadHeaders(headers)) {
      params->add_request_header(key_value.first, key_value.second);
    }
  }
  params->set_prefer_cache(true);
  params->set_suggested_name(suggested_filename);
  params->set_download_source(download::DownloadSource::WEB_CONTENTS_API);
  params->set_isolation_info(rfhi.ComputeIsolationInfoForNavigation(url));

  // TODO(crbug.com/382291442): Remove feature guarding once launched.
  if (base::FeatureList::IsEnabled(
          network::features::kPopulatePermissionsPolicyOnRequest)) {
    params->set_permissions_policy(rfhi.GetPermissionsPolicy());
  }

  FrameTreeNode* frame_tree_node = rfhi.frame_tree_node();
  FrameNavigationEntry* frame_navigation_entry =
      frame_tree_node->frame_tree()
          .controller()
          .GetLastCommittedEntry()
          ->GetFrameEntry(frame_tree_node);
  if (frame_navigation_entry) {
    params->set_initiator(frame_navigation_entry->initiator_origin());
  }

  GetBrowserContext()->GetDownloadManager()->DownloadUrl(std::move(params));
}

void WebContentsImpl::GenerateMHTML(
    const MHTMLGenerationParams& params,
    base::OnceCallback<void(int64_t)> callback) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::GenerateMHTML");
  MHTMLGenerationManager::GetInstance()->SaveMHTML(this, params,
                                                   std::move(callback));
}

const std::string& WebContentsImpl::GetContentsMimeType() {
  return GetPrimaryPage().GetContentsMimeType();
}

blink::RendererPreferences* WebContentsImpl::GetMutableRendererPrefs() {
  return &renderer_preferences_;
}

void WebContentsImpl::DragSourceEndedAt(float client_x,
                                        float client_y,
                                        float screen_x,
                                        float screen_y,
                                        ui::mojom::DragOperation operation,
                                        RenderWidgetHost* source_rwh) {
  OPTIONAL_TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("content.verbose"),
                        "WebContentsImpl::DragSourceEndedAt");
  if (source_rwh) {
    source_rwh->DragSourceEndedAt(gfx::PointF(client_x, client_y),
                                  gfx::PointF(screen_x, screen_y), operation,
                                  base::DoNothing());
  }
}

void WebContentsImpl::LoadStateChanged(network::mojom::LoadInfoPtr load_info) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::LoadStateChanged", "host",
                        load_info->host, "load_state", load_info->load_state);

  // If the new load state isn't progressed as far as the current loading state
  // or both are sending an upload and the upload is smaller, return early
  // discarding the new load state.
  if (load_info_timestamp_ + kUpdateLoadStatesInterval > load_info->timestamp &&
      (load_state_.state > load_info->load_state ||
       (load_state_.state == load_info->load_state &&
        load_state_.state == net::LOAD_STATE_SENDING_REQUEST &&
        upload_size_ > load_info->upload_size))) {
    return;
  }

  load_info_timestamp_ = load_info->timestamp;
  std::u16string host16 = url_formatter::IDNToUnicode(load_info->host);
  // Drop no-op updates.
  if (load_state_.state == load_info->load_state &&
      load_state_.param == load_info->state_param &&
      upload_position_ == load_info->upload_position &&
      upload_size_ == load_info->upload_size && load_state_host_ == host16) {
    return;
  }
  load_state_ = net::LoadStateWithParam(
      static_cast<net::LoadState>(load_info->load_state),
      load_info->state_param);
  load_state_host_ = host16;
}

void WebContentsImpl::SetVisibilityAndNotifyObservers(Visibility visibility) {
  OPTIONAL_TRACE_EVENT1("content",
                        "WebContentsImpl::SetVisibilityAndNotifyObservers",
                        "visibility", static_cast<int>(visibility));
  const Visibility previous_visibility = visibility_;
  visibility_ = visibility;

  // Notify observers if the visibility changed or if WasShown() is being called
  // for the first time.
  if (visibility != previous_visibility ||
      (visibility == Visibility::VISIBLE && !did_first_set_visible_)) {
    SCOPED_UMA_HISTOGRAM_TIMER("WebContentsObserver.OnVisibilityChanged");
    observers_.NotifyObservers(&WebContentsObserver::OnVisibilityChanged,
                               visibility);
  }
}

void WebContentsImpl::NotifyWebContentsFocused(
    RenderWidgetHost* render_widget_host) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::NotifyWebContentsFocused",
                        "render_widget_host", render_widget_host);
  observers_.NotifyObservers(&WebContentsObserver::OnWebContentsFocused,
                             render_widget_host);
}

void WebContentsImpl::NotifyWebContentsLostFocus(
    RenderWidgetHost* render_widget_host) {
  OPTIONAL_TRACE_EVENT1("content",
                        "WebContentsImpl::NotifyWebContentsLostFocus",
                        "render_widget_host", render_widget_host);
  observers_.NotifyObservers(&WebContentsObserver::OnWebContentsLostFocus,
                             render_widget_host);
}

void WebContentsImpl::SystemDragEnded(RenderWidgetHost* source_rwh) {
  if (delegate_) {
    delegate_->HandleDragEnded();
  }

  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::SystemDragEnded",
                        "render_widget_host", source_rwh);
  if (source_rwh) {
    source_rwh->DragSourceSystemDragEnded();
  }
}

void WebContentsImpl::SetClosedByUserGesture(bool value) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::SetClosedByUserGesture",
                        "value", value);
  closed_by_user_gesture_ = value;
}

bool WebContentsImpl::GetClosedByUserGesture() {
  return closed_by_user_gesture_;
}

int WebContentsImpl::GetMinimumZoomPercent() {
  return minimum_zoom_percent_;
}

int WebContentsImpl::GetMaximumZoomPercent() {
  return maximum_zoom_percent_;
}

void WebContentsImpl::SetPageScale(float scale_factor) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::SetPageScale",
                        "scale_factor", scale_factor);
  GetPrimaryMainFrame()->GetAssociatedLocalMainFrame()->SetScaleFactor(
      scale_factor);
}

gfx::Size WebContentsImpl::GetPreferredSize() {
  return IsBeingCaptured() ? preferred_size_for_capture_ : preferred_size_;
}

bool WebContentsImpl::GotResponseToPointerLockRequest(
    blink::mojom::PointerLockResult result) {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::GotResponseToPointerLockRequest");
  if (pointer_lock_widget_) {
    auto* web_contents =
        WebContentsImpl::FromRenderWidgetHostImpl(pointer_lock_widget_);
    if (web_contents != this) {
      return web_contents->GotResponseToPointerLockRequest(result);
    }

    if (pointer_lock_widget_->GotResponseToPointerLockRequest(result)) {
      return true;
    }
  }

  for (WebContentsImpl* current = this; current;
       current = current->GetOuterWebContents()) {
    current->pointer_lock_widget_ = nullptr;
  }

  return false;
}

void WebContentsImpl::GotPointerLockPermissionResponse(bool allowed) {
  GotResponseToPointerLockRequest(
      allowed ? blink::mojom::PointerLockResult::kSuccess
              : blink::mojom::PointerLockResult::kPermissionDenied);
}

void WebContentsImpl::DropPointerLockForTesting() {
  if (pointer_lock_widget_) {
    pointer_lock_widget_->RejectPointerLockOrUnlockIfNecessary(
        blink::mojom::PointerLockResult::kUnknownError);
    for (WebContentsImpl* current = this; current;
         current = current->GetOuterWebContents()) {
      current->pointer_lock_widget_ = nullptr;
    }
  }
}

bool WebContentsImpl::GotResponseToKeyboardLockRequest(bool allowed) {
  OPTIONAL_TRACE_EVENT1("content",
                        "WebContentsImpl::GotResponseToKeyboardLockRequest",
                        "allowed", allowed);
  if (!keyboard_lock_widget_) {
    return false;
  }
  // Exits early here if GotResponseToKeyboardLockRequest() was called from
  // the dtor for `this`.
  if (WebContentsImpl::FromRenderWidgetHostImpl(keyboard_lock_widget_) !=
      this) {
    return false;
  }
  // KeyboardLock is only supported when called by the top-level browsing
  // context and is not supported in embedded content scenarios.
  if (GetOuterWebContents()) {
    keyboard_lock_widget_->GotResponseToKeyboardLockRequest(false);
    return false;
  }
  keyboard_lock_widget_->GotResponseToKeyboardLockRequest(allowed);
  return true;
}

bool WebContentsImpl::HasOpener() {
  return GetOpener() != nullptr;
}

RenderFrameHostImpl* WebContentsImpl::GetOpener() {
  FrameTreeNode* opener_ftn = primary_frame_tree_.root()->opener();
  return opener_ftn ? opener_ftn->current_frame_host() : nullptr;
}

bool WebContentsImpl::HasLiveOriginalOpenerChain() {
  return GetFirstWebContentsInLiveOriginalOpenerChain() != nullptr;
}

WebContents* WebContentsImpl::GetFirstWebContentsInLiveOriginalOpenerChain() {
  FrameTreeNode* opener_ftn =
      primary_frame_tree_.root()
          ->first_live_main_frame_in_original_opener_chain();
  return opener_ftn ? WebContents::FromRenderFrameHost(
                          opener_ftn->current_frame_host())
                    : nullptr;
}

#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
void WebContentsImpl::DidChooseColorInColorChooser(SkColor color) {
  OPTIONAL_TRACE_EVENT1("content",
                        "WebContentsImpl::DidChooseColorInColorChooser",
                        "color", color);
  if (color_chooser_holder_) {
    color_chooser_holder_->DidChooseColorInColorChooser(color);
  }
}

void WebContentsImpl::DidEndColorChooser() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::DidEndColorChooser");
  color_chooser_holder_.reset();
}
#endif

int WebContentsImpl::DownloadImageFromAxNode(const ui::AXTreeID tree_id,
                                             const ui::AXNodeID node_id,
                                             const gfx::Size& preferred_size,
                                             uint32_t max_bitmap_size,
                                             bool bypass_cache,
                                             ImageDownloadCallback callback) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::DownloadImage",
                        "tree_id,node_id",
                        tree_id.ToString() + "," + base::ToString(node_id));
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  const int download_id = GetNextDownloadId();

  RenderFrameHostImpl* target_frame =
      RenderFrameHostImpl::FromAXTreeID(tree_id);
  if (!target_frame || !target_frame->IsRenderFrameLive()) {
    // If the renderer process is dead (i.e. crash, or memory pressure on
    // Android), the downloader service will be invalid. Pre-Mojo, this would
    // hang the callback indefinitely since the IPC would be dropped. Now,
    // respond with a 400 HTTP error code to indicate that something went wrong.
    // Additionally for A11y requests, send an empty URL back since it won't be
    // used anyways.
    GetUIThreadTaskRunner({})->PostTask(
        FROM_HERE,
        base::BindOnce(&WebContentsImpl::OnDidDownloadImage,
                       weak_factory_.GetWeakPtr(),
                       target_frame ? target_frame->GetWeakPtr() : nullptr,
                       std::move(callback), download_id, GURL(), 400,
                       std::vector<SkBitmap>(), std::vector<gfx::Size>()));
    return download_id;
  }
  CHECK_EQ(target_frame->GetAXTreeID(), tree_id);
  target_frame->GetMojoImageDownloader()->DownloadImageFromAxNode(
      node_id, preferred_size, max_bitmap_size, bypass_cache,
      base::BindOnce(&WebContentsImpl::OnDidDownloadImage,
                     weak_factory_.GetWeakPtr(), target_frame->GetWeakPtr(),
                     std::move(callback), download_id, GURL()));
  return download_id;
}

int WebContentsImpl::DownloadImage(
    const GURL& url,
    bool is_favicon,
    const gfx::Size& preferred_size,
    uint32_t max_bitmap_size,
    bool bypass_cache,
    WebContents::ImageDownloadCallback callback) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::DownloadImage", "url",
                        url);
  return DownloadImageInFrame(GlobalRenderFrameHostId(), url, is_favicon,
                              preferred_size, max_bitmap_size, bypass_cache,
                              std::move(callback));
}

int WebContentsImpl::DownloadImageInFrame(
    const GlobalRenderFrameHostId& initiator_frame_routing_id,
    const GURL& url,
    bool is_favicon,
    const gfx::Size& preferred_size,
    uint32_t max_bitmap_size,
    bool bypass_cache,
    WebContents::ImageDownloadCallback callback) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::DownloadImageInFrame");
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  const int download_id = GetNextDownloadId();

  RenderFrameHostImpl* initiator_frame =
      initiator_frame_routing_id.child_id
          ? RenderFrameHostImpl::FromID(initiator_frame_routing_id)
          : GetPrimaryMainFrame();
  if (!initiator_frame->IsRenderFrameLive()) {
    // If the renderer process is dead (i.e. crash, or memory pressure on
    // Android), the downloader service will be invalid. Pre-Mojo, this would
    // hang the callback indefinitely since the IPC would be dropped. Now,
    // respond with a 400 HTTP error code to indicate that something went wrong.
    GetUIThreadTaskRunner({})->PostTask(
        FROM_HERE,
        base::BindOnce(
            &WebContentsImpl::OnDidDownloadImage, weak_factory_.GetWeakPtr(),
            initiator_frame->GetWeakPtr(), std::move(callback), download_id,
            url, 400, std::vector<SkBitmap>(), std::vector<gfx::Size>()));
    return download_id;
  }

  initiator_frame->GetMojoImageDownloader()->DownloadImage(
      url, is_favicon, preferred_size, max_bitmap_size, bypass_cache,
      base::BindOnce(&WebContentsImpl::OnDidDownloadImage,
                     weak_factory_.GetWeakPtr(), initiator_frame->GetWeakPtr(),
                     std::move(callback), download_id, url));
  return download_id;
}

void WebContentsImpl::Find(int request_id,
                           const std::u16string& search_text,
                           blink::mojom::FindOptionsPtr options,
                           bool skip_delay) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::Find");
  // Cowardly refuse to search for no text.
  if (search_text.empty()) {
    NOTREACHED();
  }

  GetOrCreateFindRequestManager()->Find(request_id, search_text,
                                        std::move(options), skip_delay);
}

void WebContentsImpl::StopFinding(StopFindAction action) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::StopFinding");
  if (FindRequestManager* manager = GetFindRequestManager()) {
    manager->StopFinding(action);
  }
}

bool WebContentsImpl::WasEverAudible() {
  return was_ever_audible_;
}

void WebContentsImpl::ExitFullscreen(bool will_cause_resize) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::ExitFullscreen");
  // Clean up related state and initiate the fullscreen exit.
  GetRenderViewHost()->GetWidget()->RejectPointerLockOrUnlockIfNecessary(
      blink::mojom::PointerLockResult::kUserRejected);
  ExitFullscreenMode(will_cause_resize);
}

base::ScopedClosureRunner WebContentsImpl::ForSecurityDropFullscreen(
    int64_t display_id) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::ForSecurityDropFullscreen",
                        "display_id", display_id);
  // Make WebContentses "related" to this instance exit HTML element fullscreen,
  // ignoring browser fullscreen and fullscreen-within-tab modes. This needs to
  // be done with two passes, because it is simple to walk _up_ the chain of
  // openers and outer contents, but it not simple to walk _down_ the chain.
  auto is_fullscreen = [](WebContentsImpl* tab, int64_t display_id) {
    if (!tab || !tab->GetDelegate()) {
      return false;
    }
    const FullscreenState state = tab->GetDelegate()->GetFullscreenState(tab);
    return state.target_mode == FullscreenMode::kContent &&
           (display_id == display::kInvalidDisplayId ||
            state.target_display_id == display::kInvalidDisplayId ||
            state.target_display_id == display_id);
  };

  // First, determine if any fullscreen WebContents has this WebContents as an
  // upstream contents. Drop that WebContents out of fullscreen if it does. This
  // is theoretically quadratic-ish (fullscreen contentses x each one's opener
  // length) but neither of those is expected to ever be a large number.
  auto fullscreen_set_copy = *FullscreenContentsSet(GetBrowserContext());
  for (WebContentsImpl* fullscreen_contents : fullscreen_set_copy) {
    if (is_fullscreen(fullscreen_contents, display_id)) {
      auto opener_contentses = GetAllOpeningWebContents(fullscreen_contents);
      if (opener_contentses.count(this)) {
        fullscreen_contents->ExitFullscreen(true);
      }
    }
  }

  // Second, walk upstream from this WebContents, and drop the fullscreen of
  // all WebContentses that are in fullscreen. Block all the WebContentses in
  // the chain from entering fullscreen while the returned closure runner is
  // alive. It's OK that this set doesn't contain downstream WebContentses, as
  // any request to enter fullscreen will have the upstream of the WebContents
  // checked. (See CanEnterFullscreenMode().)

  std::vector<base::WeakPtr<WebContentsImpl>> blocked_contentses;

  for (auto* opener : GetAllOpeningWebContents(this)) {
    if (is_fullscreen(opener, display_id)) {
      opener->ExitFullscreen(true);
    }

    // ...block the WebContents from entering fullscreen until further notice.
    ++opener->fullscreen_blocker_count_;
    blocked_contentses.push_back(opener->weak_factory_.GetWeakPtr());
  }

  return base::ScopedClosureRunner(base::BindOnce(
      [](std::vector<base::WeakPtr<WebContentsImpl>> blocked_contentses) {
        for (base::WeakPtr<WebContentsImpl>& web_contents :
             blocked_contentses) {
          if (web_contents) {
            DCHECK_GT(web_contents->fullscreen_blocker_count_, 0);
            --web_contents->fullscreen_blocker_count_;
          }
        }
      },
      std::move(blocked_contentses)));
}

void WebContentsImpl::ResumeLoadingCreatedWebContents() {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::ResumeLoadingCreatedWebContents");
  if (delayed_load_url_params_.get()) {
    DCHECK(!delayed_open_url_params_);
    base::WeakPtr<NavigationHandle> navigation =
        GetController().LoadURLWithParams(*delayed_load_url_params_.get());
    if (delayed_navigation_handle_callback_ && navigation) {
      std::move(delayed_navigation_handle_callback_).Run(*navigation);
    }
    delayed_navigation_handle_callback_.Reset();
    delayed_load_url_params_.reset(nullptr);
    return;
  }

  CHECK(!delayed_navigation_handle_callback_);

  if (delayed_open_url_params_.get()) {
    OpenURL(*delayed_open_url_params_.get(),
            std::move(delayed_navigation_handle_callback_));
    delayed_open_url_params_.reset(nullptr);
    return;
  }

  // Renderer-created main frames wait for the renderer to request for them to
  // perform navigations and to be shown. We signal that this condition is
  // satisfied by calling Init().
  if (is_resume_pending_) {
    is_resume_pending_ = false;
    GetPrimaryMainFrame()->Init();
  }
}

bool WebContentsImpl::FocusLocationBarByDefault() {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::FocusLocationBarByDefault");
  if (should_focus_location_bar_by_default_) {
    return true;
  }

  return delegate_ && delegate_->ShouldFocusLocationBarByDefault(this);
}

void WebContentsImpl::DidStartNavigation(NavigationHandle* navigation_handle) {
  TRACE_EVENT1("navigation", "WebContentsImpl::DidStartNavigation",
               "navigation_handle", navigation_handle);
  base::ElapsedTimer duration;
  observers_.NotifyObservers(&WebContentsObserver::DidStartNavigation,
                             navigation_handle);
  base::TimeDelta elapsed = duration.Elapsed();
  base::UmaHistogramTimes("WebContentsObserver.DidStartNavigation", elapsed);
  base::UmaHistogramTimes(
      base::StrCat(
          {"WebContentsObserver.DidStartNavigation.",
           navigation_handle->IsInMainFrame() ? "MainFrame" : "Subframe"}),
      elapsed);
  if (navigation_handle->IsInPrimaryMainFrame()) {
    // `notify_disconnection_` may be reset during discard operations, ensure
    // this is restored when the when contents is re-navigated.
    notify_disconnection_ = true;

    // When the browser is started with about:blank as the startup URL, focus
    // the location bar (which will also select its contents) so people can
    // simply begin typing to navigate elsewhere.
    //
    // We need to be careful not to trigger this for anything other than the
    // startup navigation. In particular, if we allow an attacker to open a
    // popup to about:blank, then navigate, focusing the Omnibox will cause the
    // end of the new URL to be scrolled into view instead of the start,
    // allowing the attacker to spoof other URLs. The conditions checked here
    // are all aimed at ensuring no such attacker-controlled navigation can
    // trigger this.
    should_focus_location_bar_by_default_ =
        GetController().IsInitialNavigation() &&
        !navigation_handle->IsRendererInitiated() &&
        navigation_handle->GetURL() == url::kAboutBlankURL;
  }
}

void WebContentsImpl::DidRedirectNavigation(
    NavigationHandle* navigation_handle) {
  TRACE_EVENT1("navigation", "WebContentsImpl::DidRedirectNavigation",
               "navigation_handle", navigation_handle);
  {
    SCOPED_UMA_HISTOGRAM_TIMER("WebContentsObserver.DidRedirectNavigation");
    observers_.NotifyObservers(&WebContentsObserver::DidRedirectNavigation,
                               navigation_handle);
  }
  // Notify accessibility if this is a reload. This has to called on the
  // BrowserAccessibilityManager associated with the old RFHI.
  if (navigation_handle->GetReloadType() != ReloadType::NONE) {
    NavigationRequest* request = NavigationRequest::From(navigation_handle);
    ui::BrowserAccessibilityManager* manager =
        request->frame_tree_node()
            ->current_frame_host()
            ->browser_accessibility_manager();
    if (manager) {
      manager->UserIsReloading();
    }
  }
}

void WebContentsImpl::ReadyToCommitNavigation(
    NavigationHandle* navigation_handle) {
  TRACE_EVENT1("navigation", "WebContentsImpl::ReadyToCommitNavigation",
               "navigation_handle", navigation_handle);
  CHECK(!navigation_handle->IsSameDocument());

  // Cross-document navigation of the top-level frame resets the capture
  // handle config. Using IsInPrimaryMainFrame is valid here since the browser
  // caches this state for the active main frame only.
  if (navigation_handle->IsInPrimaryMainFrame()) {
    SetCaptureHandleConfig(blink::mojom::CaptureHandleConfig::New());
  }

  observers_.NotifyObservers(&WebContentsObserver::ReadyToCommitNavigation,
                             navigation_handle);

  // If any domains are blocked from accessing 3D APIs because they may
  // have caused the GPU to reset recently, unblock them here if the user
  // initiated this navigation. This implies that the user was involved in
  // the decision to navigate, so there's no concern about
  // denial-of-service issues. Want to do this as early as
  // possible to avoid race conditions with pages attempting to access
  // WebGL early on.
  //
  // TODO(crbug.com/41257523): currently navigations initiated by the browser
  // (reload button, reload menu option, pressing return in the Omnibox)
  // return false from HasUserGesture(). If or when that is addressed,
  // remove the check for IsRendererInitiated() below.
  //
  // TODO(crbug.com/40571460): HasUserGesture comes from the renderer
  // process and isn't validated. Until it is, don't trust it.
  if (!navigation_handle->IsRendererInitiated()) {
    GpuDataManagerImpl::GetInstance()->UnblockDomainFrom3DAPIs(
        navigation_handle->GetURL());
  }

  // SSLInfo is not needed on subframe navigations since the main-frame
  // certificate is the only one that can be inspected (using the info
  // bubble) without refreshing the page with DevTools open.
  // We don't call DidStartResourceResponse on net errors, since that results on
  // existing cert exceptions being revoked, which leads to weird behavior with
  // committed interstitials or while offline. We only need the error check for
  // the main frame case.
  if (navigation_handle->IsInMainFrame() &&
      navigation_handle->GetNetErrorCode() == net::OK) {
    static_cast<NavigationRequest*>(navigation_handle)
        ->frame_tree_node()
        ->frame_tree()
        .controller()
        .ssl_manager()
        ->DidStartResourceResponse(
            url::SchemeHostPort(navigation_handle->GetURL()),
            navigation_handle->GetSSLInfo().has_value()
                ? net::IsCertStatusError(
                      navigation_handle->GetSSLInfo()->cert_status)
                : false);
  }
}

void WebContentsImpl::DidFinishNavigation(NavigationHandle* navigation_handle) {
  TRACE_EVENT1("navigation", "WebContentsImpl::DidFinishNavigation",
               "navigation_handle", navigation_handle);

  {
    SCOPED_UMA_HISTOGRAM_TIMER("WebContentsObserver.DidFinishNavigation");
    observers_.NotifyObservers(&WebContentsObserver::DidFinishNavigation,
                               navigation_handle);
  }
  if (safe_area_insets_host_) {
    safe_area_insets_host_->DidFinishNavigation(navigation_handle);
  }

  if (navigation_handle->HasCommitted()) {
    // TODO(domfarolino, dmazzoni): Do this using WebContentsObserver. See
    // https://crbug.com/981271.
    ui::BrowserAccessibilityManager* manager =
        static_cast<RenderFrameHostImpl*>(
            navigation_handle->GetRenderFrameHost())
            ->browser_accessibility_manager();
    if (manager) {
      if (navigation_handle->IsErrorPage()) {
        manager->NavigationFailed();
      } else {
        manager->NavigationSucceeded();
      }
    }

    // TODO(crbug.com/40774464) : Move this tracking to PageImpl.
    if (navigation_handle->IsInPrimaryMainFrame() &&
        !navigation_handle->IsSameDocument()) {
      was_ever_audible_ = false;
    }

    if (!navigation_handle->IsSameDocument()) {
      last_screen_orientation_change_time_ = base::TimeTicks();
    }
  }

  // If we didn't end up on about:blank after setting this in DidStartNavigation
  // then don't focus the location bar.
  if (should_focus_location_bar_by_default_ &&
      navigation_handle->GetURL() != url::kAboutBlankURL) {
    should_focus_location_bar_by_default_ = false;
  }

  if (navigation_handle->IsInPrimaryMainFrame() &&
      first_primary_navigation_completed_) {
    RecordMaxFrameCountUMA(max_loaded_frame_count_);
  }

  // If navigation has successfully finished in the main frame, set
  // |first_primary_navigation_completed_| to true so that we will record
  // |max_loaded_frame_count_| above when future main frame navigations finish.
  if (navigation_handle->IsInPrimaryMainFrame() &&
      !navigation_handle->IsErrorPage()) {
    first_primary_navigation_completed_ = true;

    // Navigation has completed in main frame. Reset |max_loaded_frame_count_|.
    // |max_loaded_frame_count_| is not necessarily 1 if the navigation was
    // served from BackForwardCache.
    max_loaded_frame_count_ = GetFrameTreeSize(&primary_frame_tree_);

    BrowserAccessibilityStateImpl::GetInstance()->OnPageNavigationComplete();
  }

  // TODO(crbug.com/40202416): MPArch GuestView: We might need to look up the
  // preferences for the navigation here and adjust the guest, but for now
  // SetWebPreferences does not adjust the guest frame tree so we look for the
  // preferences matching the primary main frame.
  if (web_preferences_) {
    // Update the WebPreferences for this WebContents that depends on changes
    // that might occur during navigation. This will only update the preferences
    // that needs to be updated (and won't cause an update/overwrite preferences
    // that needs to stay the same after navigations).
    bool value_changed_due_to_override =
        GetContentClient()->browser()->OverrideWebPreferencesAfterNavigation(
            this, *GetPrimaryMainFrame()->GetSiteInstance(),
            web_preferences_.get());
    // We need to update the WebPreferences value on the renderer if the value
    // is changed due to the override above, or if the navigation is served from
    // the back-forward cache, because the WebPreferences value stored in the
    // renderer might be stale (because we don't send WebPreferences updates to
    // bfcached renderers). Same for prerendering.
    // TODO(rakina): Maybe handle the back-forward cache case in
    // ReadyToCommitNavigation instead?
    // TODO(crbug.com/40758687): Maybe sync RendererPreferences as well?
    if (value_changed_due_to_override ||
        NavigationRequest::From(navigation_handle)->IsPageActivation()) {
      SetWebPreferences(*web_preferences_.get());
    }
  }

  if (navigation_handle->HasCommitted() &&
      navigation_handle->IsPrerenderedPageActivation()) {
    // We defer favicon and manifest URL updates while prerendering. Upon
    // activation, we must inform interested parties about our candidate favicon
    // URLs and the manifest URL.
    DCHECK(navigation_handle->IsInPrimaryMainFrame());
    auto* rfhi = static_cast<RenderFrameHostImpl*>(
        navigation_handle->GetRenderFrameHost());
    UpdateFaviconURL(rfhi, rfhi->FaviconURLs());
    OnManifestUrlChanged(rfhi->GetPage());

    // The page might have set its title while prerendering, and if it was, we
    // skipped notifying observers then, and we need to notify them now after
    // the page is activated.
    DCHECK(navigation_handle->IsInPrimaryMainFrame());
    NavigationEntryImpl* entry = GetController().GetLastCommittedEntry();
    DCHECK(entry);
    if (!entry->GetTitle().empty()) {
      NotifyTitleUpdateForEntry(entry);
    }
  }
}

void WebContentsImpl::DidCancelNavigationBeforeStart(
    NavigationHandle* navigation_handle) {
#if BUILDFLAG(IS_ANDROID)
  if (auto* animation_manager =
          static_cast<BackForwardTransitionAnimationManagerAndroid*>(
              GetBackForwardTransitionAnimationManager())) {
    animation_manager->OnNavigationCancelledBeforeStart(navigation_handle);
  }
#endif
}

void WebContentsImpl::DidFailLoadWithError(
    RenderFrameHostImpl* render_frame_host,
    const GURL& url,
    int error_code) {
  TRACE_EVENT2("content,navigation", "WebContentsImpl::DidFailLoadWithError",
               "render_frame_host", render_frame_host, "url", url);
  observers_.NotifyObservers(&WebContentsObserver::DidFailLoad,
                             render_frame_host, url, error_code);
}

void WebContentsImpl::DraggableRegionsChanged(
    const std::vector<blink::mojom::DraggableRegionPtr>& regions) {
  if (!GetDelegate()) {
    return;
  }
  GetDelegate()->DraggableRegionsChanged(regions, this);
}

void WebContentsImpl::OnFirstContentfulPaintInPrimaryMainFrame() {
  observers_.NotifyObservers(
      &WebContentsObserver::OnFirstContentfulPaintInPrimaryMainFrame);
}

gfx::NativeWindow WebContentsImpl::GetOwnerNativeWindow() {
  return GetTopLevelNativeWindow();
}

media::PictureInPictureEventsInfo::AutoPipInfo WebContentsImpl::GetAutoPipInfo()
    const {
  return GetContentClient()->browser()->GetAutoPipInfo(*this);
}

void WebContentsImpl::OnKeepAliveRequestCreated(
    const network::ResourceRequest& resource_request,
    RenderFrameHostImpl* initiator_rfh) {
  observers_.NotifyObservers(&WebContentsObserver::OnKeepAliveRequestCreated,
                             resource_request, initiator_rfh);
}

void WebContentsImpl::NotifyChangedNavigationState(
    InvalidateTypes changed_flags) {
  NotifyNavigationStateChanged(changed_flags);
}

bool WebContentsImpl::ShouldAllowRendererInitiatedCrossProcessNavigation(
    bool is_outermost_main_frame_navigation) {
  OPTIONAL_TRACE_EVENT1(
      "content",
      "WebContentsImpl::ShouldAllowRendererInitiatedCrossProcessNavigation",
      "is_outermost_main_frame_navigation", is_outermost_main_frame_navigation);
  if (!delegate_) {
    return true;
  }
  return delegate_->ShouldAllowRendererInitiatedCrossProcessNavigation(
      is_outermost_main_frame_navigation);
}

bool WebContentsImpl::ShouldPreserveAbortedURLs() {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::ShouldPreserveAbortedURLs");
  if (!delegate_) {
    return false;
  }
  return delegate_->ShouldPreserveAbortedURLs(this);
}

void WebContentsImpl::NotifyNavigationStateChangedFromController(
    InvalidateTypes changed_flags) {
  NotifyNavigationStateChanged(changed_flags);
}

input::TouchEmulator* WebContentsImpl::GetTouchEmulator(
    bool create_if_necessary) {
  CHECK(rwh_input_event_router_);

  if (!touch_emulator_ && create_if_necessary) {
    touch_emulator_ = std::make_unique<TouchEmulatorImpl>(
        rwh_input_event_router_.get(),
        rwh_input_event_router_->last_device_scale_factor());
  }

  return touch_emulator_.get();
}

void WebContentsImpl::DidNavigateMainFramePreCommit(
    NavigationHandle* navigation_handle,
    bool navigation_is_within_page) {
  auto* request = static_cast<NavigationRequest*>(navigation_handle);
  FrameTreeNode* frame_tree_node = request->frame_tree_node();

  // The `frame_tree_node` is always a main frame.
  DCHECK(frame_tree_node->IsMainFrame());
  TRACE_EVENT1("content,navigation",
               "WebContentsImpl::DidNavigateMainFramePreCommit",
               "navigation_is_within_page", navigation_is_within_page);
  const bool is_primary_mainframe =
      frame_tree_node->GetFrameType() == FrameType::kPrimaryMainFrame;
  // If running for a non-primary main frame, early out.
  if (!is_primary_mainframe) {
    return;
  }

#if BUILDFLAG(IS_ANDROID)
  auto* animation_manager =
      static_cast<BackForwardTransitionAnimationManagerAndroid*>(
          GetBackForwardTransitionAnimationManager());
  if (animation_manager) {
    animation_manager->OnDidNavigatePrimaryMainFramePreCommit(
        request, frame_tree_node->render_manager()->current_frame_host(),
        request->GetRenderFrameHost());
  }
#endif

  // Ensure fullscreen mode is exited before committing the navigation to a
  // different page.  The next page will not start out assuming it is in
  // fullscreen mode.
  if (navigation_is_within_page) {
    // No page change?  Then, the renderer and browser can remain in fullscreen.
    return;
  }

  if (IsFullscreen()) {
    ExitFullscreen(false);
  }

  auto* rwhvb = static_cast<RenderWidgetHostViewBase*>(
      frame_tree_node->current_frame_host()->GetView());
  if (rwhvb) {
    rwhvb->OnOldViewDidNavigatePreCommit();
  }

  // Clean up keyboard lock state when navigating.
  CancelKeyboardLock(keyboard_lock_widget_);
}

void WebContentsImpl::DidNavigateMainFramePostCommit(
    RenderFrameHostImpl* render_frame_host,
    const LoadCommittedDetails& details) {
  // The render_frame_host is always a main frame.
  DCHECK(render_frame_host->is_main_frame());
  OPTIONAL_TRACE_EVENT1("content,navigation",
                        "WebContentsImpl::DidNavigateMainFramePostCommit",
                        "render_frame_host", render_frame_host);
  const bool is_primary_main_frame = render_frame_host->IsInPrimaryMainFrame();

  auto* rwhvb = static_cast<RenderWidgetHostViewBase*>(
      render_frame_host->GetMainFrame()->GetView());

  if (details.is_navigation_to_different_page()) {
    if (is_primary_main_frame) {
      // Clear the status bubble. This is a workaround for a bug where WebKit
      // doesn't let us know that the cursor left an element during a
      // transition (this is also why the mouse cursor remains as a hand after
      // clicking on a link); see bugs 1184641 and 980803. We don't want to
      // clear the bubble when a user navigates to a named anchor in the same
      // page.
      ClearTargetURL();

      // Run the post-commit tasks on the new View.
      if (rwhvb) {
        rwhvb->OnNewViewDidNavigatePostCommit();
      }
    }
  }

  PageImpl& page = render_frame_host->GetPage();
  if (page.IsPrimary()) {
    // The following events will not fire again if the this is a back-forward
    // cache restore or prerendering activation. Fire them ourselves if needed.
    if (details.is_navigation_to_different_page() &&
        page.did_first_visually_non_empty_paint()) {
      OnFirstVisuallyNonEmptyPaint(page);
    }
    OnThemeColorChanged(page);
    OnBackgroundColorChanged(page);
    DidInferColorScheme(page);
    AXTreeIDForMainFrameHasChanged();
  }
}

void WebContentsImpl::DidNavigateAnyFramePostCommit(
    RenderFrameHostImpl* render_frame_host,
    const LoadCommittedDetails& details) {
  OPTIONAL_TRACE_EVENT1("content,navigation",
                        "WebContentsImpl::DidNavigateAnyFramePostCommit",
                        "render_frame_host", render_frame_host);

  // This function can be called by prerendered frames or other inactive frames,
  // we want to guard the dialog cancellations below.
  const bool is_active = render_frame_host->IsActive();

  // If we navigate off the active non-fenced frame page, close all JavaScript
  // dialogs. We do not cancel the dialogs for fenced frames because it can be
  // used as a communication channel. Please see also:
  // RenderFrameHostManager::UnloadOldFrame in
  // content/browser/renderer_host/render_frame_host_manager.cc
  //
  // TODO(crbug.com/40215909): Note that fenced frames cannot open modal dialogs
  // so this only affects dialogs outside the fenced frame tree. If this is ever
  // changed then the navigation should be deferred till the dialog from within
  // the fenced frame is open.
  if (is_active && !render_frame_host->IsNestedWithinFencedFrame() &&
      !details.is_same_document) {
    CancelActiveAndPendingDialogs();
  }

  // If this is a user-initiated navigation, start allowing JavaScript dialogs
  // again.
  //
  // TODO(crbug.com/40249773): Consider using the actual value of
  // "whether a navigation started with user activation or not" instead of
  // has_user_gesture, which might get filtered out when navigating from
  // proxies. If so, we can remove tracking of
  // `last_committed_common_params_has_user_gesture` entirely.
  if (render_frame_host->last_committed_common_params_has_user_gesture()) {
    DCHECK(is_active);
    CancelDialogManagerDialogs(/*reset_state=*/true);
  }
}

void WebContentsImpl::DidUpdateNavigationHandleTiming(
    NavigationHandle* navigation_handle) {
  SCOPED_UMA_HISTOGRAM_TIMER(
      "WebContentsObserver.DidUpdateNavigationHandleTiming");
  observers_.NotifyObservers(
      &WebContentsObserver::DidUpdateNavigationHandleTiming, navigation_handle);
}

bool WebContentsImpl::CanOverscrollContent() const {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::CanOverscrollContent");
  // Disable overscroll when touch emulation is on. See crbug.com/369938.
  if (force_disable_overscroll_content_) {
    return false;
  }
  return delegate_ && delegate_->CanOverscrollContent();
}

void WebContentsImpl::OnThemeColorChanged(PageImpl& page) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::OnThemeColorChanged",
                        "page", page);
  if (!page.IsPrimary()) {
    return;
  }

  if (page.did_first_visually_non_empty_paint() &&
      last_sent_theme_color_ != page.theme_color()) {
    observers_.NotifyObservers(&WebContentsObserver::DidChangeThemeColor);
    last_sent_theme_color_ = page.theme_color();
  }
}

void WebContentsImpl::OnBackgroundColorChanged(PageImpl& page) {
  if (!page.IsPrimary()) {
    return;
  }

  if (page.did_first_visually_non_empty_paint() &&
      last_sent_background_color_ != page.background_color()) {
    observers_.NotifyObservers(&WebContentsObserver::OnBackgroundColorChanged);
    last_sent_background_color_ = page.background_color();
    return;
  }

  if (page.background_color().has_value()) {
    if (auto* view = GetRenderWidgetHostView()) {
      static_cast<RenderWidgetHostViewBase*>(view)->SetContentBackgroundColor(
          page.background_color().value());
    }
  }
}

void WebContentsImpl::DidInferColorScheme(PageImpl& page) {
  // If the page is primary, notify embedders that the current inferred color
  // scheme for this WebContents has changed.
  if (page.IsPrimary()) {
    observers_.NotifyObservers(&WebContentsObserver::InferredColorSchemeUpdated,
                               page.inferred_color_scheme());
    if (page.inferred_color_scheme().has_value()) {
      bool dark = page.inferred_color_scheme().value() ==
                  blink::mojom::PreferredColorScheme::kDark;
      base::UmaHistogramBoolean("Power.DarkMode.InferredDarkPageColorScheme",
                                dark);
      if (web_preferences_ && web_preferences_->preferred_color_scheme ==
                                  blink::mojom::PreferredColorScheme::kDark) {
        base::UmaHistogramBoolean(
            "Power.DarkMode.DarkColorScheme.InferredDarkPageColorScheme", dark);
      }
    }
  }
}

void WebContentsImpl::OnVirtualKeyboardModeChanged(PageImpl& page) {
  if (!page.IsPrimary()) {
    return;
  }

  observers_.NotifyObservers(&WebContentsObserver::VirtualKeyboardModeChanged,
                             page.virtual_keyboard_mode());
}

void WebContentsImpl::DidLoadResourceFromMemoryCache(
    RenderFrameHostImpl* source,
    const GURL& url,
    const std::string& http_method,
    const std::string& mime_type,
    network::mojom::RequestDestination request_destination,
    bool include_credentials) {
  OPTIONAL_TRACE_EVENT2("content",
                        "WebContentsImpl::DidLoadResourceFromMemoryCache",
                        "render_frame_host", source, "url", url);
  observers_.NotifyObservers(
      &WebContentsObserver::DidLoadResourceFromMemoryCache, source, url,
      mime_type, request_destination);

  if (!url.is_valid() || !url.SchemeIsHTTPOrHTTPS()) {
    return;
  }

  StoragePartition* partition = source->GetProcess()->GetStoragePartition();

  // This method should only be called for resource loads (not navigations), so
  // CHECK that here using `request_destination`. Note that
  // `network::mojom::RequestDestination::kObject` and
  // `network::mojom::RequestDestination::kEmbed` can correspond to navigations
  // (see `blink::IsRequestDestinationFrame()`) but can also correspond to
  // resource loads, so exclude those from the CHECK.
  CHECK(request_destination != network::mojom::RequestDestination::kDocument);
  CHECK(!network::IsRequestDestinationEmbeddedFrame(request_destination));

  partition->GetNetworkContext()->NotifyExternalCacheHit(
      url, http_method, source->GetNetworkIsolationKey(),
      /*include_credentials=*/include_credentials);
}

void WebContentsImpl::PrimaryMainDocumentElementAvailable() {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::PrimaryMainDocumentElementAvailable");
  SCOPED_UMA_HISTOGRAM_TIMER(
      "WebContentsObserver.PrimaryMainDocumentElementAvailable");
  observers_.NotifyObservers(
      &WebContentsObserver::PrimaryMainDocumentElementAvailable);
}

void WebContentsImpl::PassiveInsecureContentFound(const GURL& resource_url) {
  OPTIONAL_TRACE_EVENT1("content",
                        "WebContentsImpl::PassiveInsecureContentFound",
                        "resource_url", resource_url);
  if (delegate_) {
    delegate_->PassiveInsecureContentFound(resource_url);
  }
}

bool WebContentsImpl::ShouldAllowRunningInsecureContent(
    bool allowed_per_prefs,
    const url::Origin& origin,
    const GURL& resource_url) {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::ShouldAllowRunningInsecureContent");
  if (delegate_) {
    return delegate_->ShouldAllowRunningInsecureContent(this, allowed_per_prefs,
                                                        origin, resource_url);
  }

  return allowed_per_prefs;
}

void WebContentsImpl::ViewSource(RenderFrameHostImpl* frame) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::ViewSource",
                        "render_frame_host", frame);
  DCHECK_EQ(this, WebContents::FromRenderFrameHost(frame));

  // Don't do anything if there is no |delegate_| that could accept and show the
  // new WebContents containing the view-source.
  if (!delegate_) {
    return;
  }

  // Use the last committed entry, since the pending entry hasn't loaded yet and
  // won't be copied into the cloned tab.
  NavigationEntryImpl* last_committed_entry =
      frame->frame_tree()->controller().GetLastCommittedEntry();
  if (!last_committed_entry) {
    return;
  }

  FrameNavigationEntry* frame_entry =
      last_committed_entry->GetFrameEntry(frame->frame_tree_node());
  if (!frame_entry) {
    return;
  }

  // Any new WebContents opened while this WebContents is in fullscreen can be
  // used to confuse the user, so drop fullscreen.
  base::ScopedClosureRunner fullscreen_block =
      ForSecurityDropFullscreen(/*display_id=*/display::kInvalidDisplayId);
  // The new view source contents will be independent of this contents, so
  // release the fullscreen block.
  fullscreen_block.RunAndReset();

  // We intentionally don't share the SiteInstance with the original frame so
  // that view source has a consistent process model and always ends up in a new
  // process (https://crbug.com/699493).
  scoped_refptr<SiteInstanceImpl> site_instance_for_view_source;
  // Referrer and initiator are not important, because view-source should not
  // hit the network, but should be served from the cache instead.
  Referrer referrer_for_view_source;
  std::optional<url::Origin> initiator_for_view_source = std::nullopt;
  std::optional<GURL> initiator_base_url_for_view_source = std::nullopt;
  // Do not restore title, derive it from the url.
  std::u16string title_for_view_source;
  auto navigation_entry = std::make_unique<NavigationEntryImpl>(
      site_instance_for_view_source, frame_entry->url(),
      referrer_for_view_source, initiator_for_view_source,
      initiator_base_url_for_view_source, title_for_view_source,
      ui::PAGE_TRANSITION_LINK,
      /* is_renderer_initiated = */ false,
      /* blob_url_loader_factory = */ nullptr, /* is_initial_entry = */ false);
  const GURL url(content::kViewSourceScheme + std::string(":") +
                 frame_entry->url().spec());
  navigation_entry->SetVirtualURL(url);

  // View source opens the URL in a new tab as a top-level navigation. A
  // top-level navigation may have a different IsolationInfo than the source
  // iframe, so preserve the IsolationInfo from the origin frame, to use the
  // same network shard and increase chances of a cache hit.
  navigation_entry->set_isolation_info(
      frame->ComputeIsolationInfoForNavigation(navigation_entry->GetURL()));

  // Do not restore scroller position.
  // TODO(creis, lukasza, arthursonzogni): Do not reuse the original PageState,
  // but start from a new one and only copy the needed data.
  const blink::PageState& new_page_state =
      frame_entry->page_state().RemoveScrollOffset();

  scoped_refptr<FrameNavigationEntry> new_frame_entry =
      navigation_entry->root_node()->frame_entry;
  new_frame_entry->set_method(frame_entry->method());
  new_frame_entry->SetPageState(new_page_state);

  // Create a new WebContents, which is used to display the source code.
  std::unique_ptr<WebContents> view_source_contents =
      Create(CreateParams(GetBrowserContext()));

  // Restore the previously created NavigationEntry.
  std::vector<std::unique_ptr<NavigationEntry>> navigation_entries;
  navigation_entries.push_back(std::move(navigation_entry));
  view_source_contents->GetController().Restore(0, RestoreType::kRestored,
                                                &navigation_entries);

  // Add |view_source_contents| as a new tab.
  constexpr bool kUserGesture = true;
  bool ignored_was_blocked;
  delegate_->AddNewContents(this, std::move(view_source_contents), url,
                            WindowOpenDisposition::NEW_FOREGROUND_TAB,
                            blink::mojom::WindowFeatures(), kUserGesture,
                            &ignored_was_blocked);
  // Note that the |delegate_| could have deleted |view_source_contents| during
  // AddNewContents method call.
}

void WebContentsImpl::ResourceLoadComplete(
    RenderFrameHostImpl* render_frame_host,
    const GlobalRequestID& request_id,
    blink::mojom::ResourceLoadInfoPtr resource_load_info) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::ResourceLoadComplete",
                        "render_frame_host", render_frame_host, "request_id",
                        request_id);
  const blink::mojom::ResourceLoadInfo& resource_load_info_ref =
      *resource_load_info;
  observers_.NotifyObservers(&WebContentsObserver::ResourceLoadComplete,
                             render_frame_host, request_id,
                             resource_load_info_ref);
}

const blink::web_pref::WebPreferences&
WebContentsImpl::GetOrCreateWebPreferences() {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::GetOrCreateWebPreferences");
  // Compute WebPreferences based on the current state if it's null.
  if (!web_preferences_) {
    OnWebPreferencesChanged();
  }

  CHECK(web_preferences_)
      << "WebPreferences is not created because GetOrCreateWebPreferences() "
      << "is called before OnWebPreferencesChanged() returns.";
  return *web_preferences_.get();
}

void WebContentsImpl::SetWebPreferences(
    const blink::web_pref::WebPreferences& prefs) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::SetWebPreferences");
  web_preferences_ = std::make_unique<blink::web_pref::WebPreferences>(prefs);
  // Get all the RenderViewHosts (except the ones for currently back-forward
  // cached pages), and make them send the current WebPreferences
  // to the renderer. WebPreferences updates for back-forward cached pages will
  // be sent when we restore those pages from the back-forward cache.
  primary_frame_tree_.ForEachRenderViewHost(
      [](RenderViewHostImpl* rvh) { rvh->SendWebPreferencesToRenderer(); });
}

std::optional<SkColor> WebContentsImpl::GetBaseBackgroundColor() {
  return page_base_background_color_;
}

blink::ColorProviderColorMaps WebContentsImpl::GetColorProviderColorMaps()
    const {
  const auto* color_mode_source = GetColorProviderSource();

  // Unlike preferred color scheme, ForcedColors should always use the
  // default color provider source, which reflects the NativeTheme web instance.
  // This is because the Page colors feature only modifies the Forced colors
  // mode for web without affecting the UI.
  const auto* forced_colors_source = DefaultColorProviderSource::GetInstance();
  ui::ColorProviderKey::ForcedColors forced_colors =
      forced_colors_source->GetForcedColors();
  if (forced_colors == ui::ColorProviderKey::ForcedColors::kNone) {
    forced_colors = ui::ColorProviderKey::ForcedColors::kSystem;
  }

  return blink::ColorProviderColorMaps{
      color_mode_source->GetRendererColorMap(
          ui::ColorProviderKey::ColorMode::kLight,
          ui::ColorProviderKey::ForcedColors::kNone),
      color_mode_source->GetRendererColorMap(
          ui::ColorProviderKey::ColorMode::kDark,
          ui::ColorProviderKey::ForcedColors::kNone),
      forced_colors_source->GetRendererColorMap(
          forced_colors_source->GetColorMode(), forced_colors)};
}

void WebContentsImpl::PrintCrossProcessSubframe(
    const gfx::Rect& rect,
    int document_cookie,
    RenderFrameHostImpl* subframe_host) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::PrintCrossProcessSubframe",
                        "subframe", subframe_host);
  auto* outer_contents = GetOuterWebContents();
  if (outer_contents) {
    // When an extension or app page is printed, the content should be
    // composited with outer content, so the outer contents should handle the
    // print request.
    outer_contents->PrintCrossProcessSubframe(rect, document_cookie,
                                              subframe_host);
    return;
  }

  // If there is no delegate such as in tests or during deletion, do nothing.
  if (!delegate_) {
    return;
  }

  delegate_->PrintCrossProcessSubframe(this, rect, document_cookie,
                                       subframe_host);
}

void WebContentsImpl::CapturePaintPreviewOfCrossProcessSubframe(
    const gfx::Rect& rect,
    const base::UnguessableToken& guid,
    RenderFrameHostImpl* render_frame_host) {
  OPTIONAL_TRACE_EVENT1(
      "content", "WebContentsImpl::CapturePaintPreviewOfCrossProcessSubframe",
      "render_frame_host", render_frame_host);
  if (!delegate_) {
    return;
  }
  delegate_->CapturePaintPreviewOfSubframe(this, rect, guid, render_frame_host);
}

#if BUILDFLAG(IS_ANDROID)
base::android::ScopedJavaLocalRef<jobject>
WebContentsImpl::GetJavaRenderFrameHostDelegate() {
  return GetJavaWebContents();
}
#endif

void WebContentsImpl::DOMContentLoaded(RenderFrameHostImpl* render_frame_host) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::DOMContentLoaded",
                        "render_frame_host", render_frame_host);
  SCOPED_UMA_HISTOGRAM_TIMER("WebContentsObserver.DOMContentLoaded");
  observers_.NotifyObservers(&WebContentsObserver::DOMContentLoaded,
                             render_frame_host);
}

void WebContentsImpl::OnDidFinishLoad(RenderFrameHostImpl* render_frame_host,
                                      const GURL& url) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::OnDidFinishLoad",
                        "render_frame_host", render_frame_host, "url", url);
  GURL validated_url(url);
  render_frame_host->GetProcess()->FilterURL(false, &validated_url);

  {
    SCOPED_UMA_HISTOGRAM_TIMER("WebContentsObserver.DidFinishLoad");
    observers_.NotifyObservers(&WebContentsObserver::DidFinishLoad,
                               render_frame_host, validated_url);
  }
  size_t tree_size = GetFrameTreeSize(&primary_frame_tree_);
  if (max_loaded_frame_count_ < tree_size) {
    max_loaded_frame_count_ = tree_size;
  }

  if (!render_frame_host->GetParentOrOuterDocument()) {
    UMA_HISTOGRAM_COUNTS_1000("Navigation.MainFrame.FrameCount", tree_size);
  }
}

bool WebContentsImpl::IsAllowedToGoToEntryAtOffset(int32_t offset) {
  // TODO(crbug.com/40165695): This should probably be renamed to
  // WebContentsDelegate::IsAllowedToGoToEntryAtOffset or
  // ShouldGoToEntryAtOffset
  return !delegate_ || delegate_->OnGoToEntryOffset(offset);
}

void WebContentsImpl::OnPageScaleFactorChanged(PageImpl& source) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::OnPageScaleFactorChanged",
                        "source", source);

  if (source.IsPrimary()) {
    observers_.NotifyObservers(&WebContentsObserver::OnPageScaleFactorChanged,
                               source.GetPageScaleFactor());
  }
}

void WebContentsImpl::EnumerateDirectory(
    base::WeakPtr<FileChooserImpl> file_chooser,
    RenderFrameHost* render_frame_host,
    scoped_refptr<FileChooserImpl::FileSelectListenerImpl> listener,
    const base::FilePath& directory_path) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::EnumerateDirectory",
                        "render_frame_host", render_frame_host,
                        "directory_path", directory_path);
  absl::Cleanup cancel_chooser = [&listener] {
    listener->FileSelectionCanceled();
  };
  if (visibility_ == Visibility::HIDDEN) {
    // Do not allow background tab to open file chooser.
    return;
  }
  if (active_file_chooser_) {
    // Only allow one active file chooser at one time.
    return;
  }

  // Any explicit focusing of another window while this WebContents is in
  // fullscreen can be used to confuse the user, so drop fullscreen.
  base::ScopedClosureRunner fullscreen_block =
      ForSecurityDropFullscreen(/*display_id=*/display::kInvalidDisplayId);
  listener->SetFullscreenBlock(std::move(fullscreen_block));

  if (delegate_) {
    active_file_chooser_ = std::move(file_chooser);
    delegate_->EnumerateDirectory(this, std::move(listener), directory_path);
    std::move(cancel_chooser).Cancel();
  }
}

void WebContentsImpl::RegisterProtocolHandler(RenderFrameHostImpl* source,
                                              const std::string& protocol,
                                              const GURL& url,
                                              bool user_gesture) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::RegisterProtocolHandler",
                        "render_frame_host", source, "protocol", protocol);
  // TODO(nick): Do we need to apply FilterURL to |url|?
  if (!delegate_) {
    return;
  }

  blink::ProtocolHandlerSecurityLevel security_level =
      delegate_->GetProtocolHandlerSecurityLevel(source);

  // Run the protocol handler arguments normalization process defined in the
  // spec.
  // https://html.spec.whatwg.org/multipage/system-state.html#normalize-protocol-handler-parameters
  if (!AreValidRegisterProtocolHandlerArguments(
          protocol, url, source->GetLastCommittedOrigin(), security_level)) {
    ReceivedBadMessage(source->GetProcess(),
                       bad_message::REGISTER_PROTOCOL_HANDLER_INVALID_URL);
    return;
  }

  delegate_->RegisterProtocolHandler(source, protocol, url, user_gesture);
}

void WebContentsImpl::UnregisterProtocolHandler(RenderFrameHostImpl* source,
                                                const std::string& protocol,
                                                const GURL& url,
                                                bool user_gesture) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::UnregisterProtocolHandler",
                        "render_frame_host", source, "protocol", protocol);
  // TODO(nick): Do we need to apply FilterURL to |url|?
  if (!delegate_) {
    return;
  }

  blink::ProtocolHandlerSecurityLevel security_level =
      delegate_->GetProtocolHandlerSecurityLevel(source);

  if (!AreValidRegisterProtocolHandlerArguments(
          protocol, url, source->GetLastCommittedOrigin(), security_level)) {
    ReceivedBadMessage(source->GetProcess(),
                       bad_message::REGISTER_PROTOCOL_HANDLER_INVALID_URL);
    return;
  }

  delegate_->UnregisterProtocolHandler(source, protocol, url, user_gesture);
}

base::ScopedClosureRunner WebContentsImpl::MarkAudible() {
  auto audible_client = audio_stream_monitor_.RegisterAudibleClient(
      GetPrimaryMainFrame()->GetGlobalId());
  return base::ScopedClosureRunner(
      base::DoNothingWithBoundArgs(std::move(audible_client)));
}

void WebContentsImpl::DomOperationResponse(RenderFrameHost* render_frame_host,
                                           const std::string& json_string) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::DomOperationResponse",
                        "render_frame_host", render_frame_host, "json_string",
                        json_string);

  observers_.NotifyObservers(&WebContentsObserver::DomOperationResponse,
                             render_frame_host, json_string);
}

void WebContentsImpl::SavableResourceLinksResponse(
    RenderFrameHostImpl* source,
    const std::vector<GURL>& resources_list,
    blink::mojom::ReferrerPtr referrer,
    const std::vector<blink::mojom::SavableSubframePtr>& subframes) {
  OPTIONAL_TRACE_EVENT1("content",
                        "WebContentsImpl::SavableResourceLinksResponse",
                        "render_frame_host", source);
  if (save_package_) {
    save_package_->SavableResourceLinksResponse(source, resources_list,
                                                std::move(referrer), subframes);
  }
}

void WebContentsImpl::SavableResourceLinksError(RenderFrameHostImpl* source) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::SavableResourceLinksError",
                        "render_frame_host", source);
  if (save_package_) {
    save_package_->SavableResourceLinksError(source);
  }
}

void WebContentsImpl::OnServiceWorkerAccessed(
    RenderFrameHost* render_frame_host,
    const GURL& scope,
    AllowServiceWorkerResult allowed) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::OnServiceWorkerAccessed",
                        "render_frame_host", render_frame_host, "scope", scope);
  // Use a variable to select between overloads.
  void (WebContentsObserver::*func)(RenderFrameHost*, const GURL&,
                                    AllowServiceWorkerResult) =
      &WebContentsObserver::OnServiceWorkerAccessed;
  observers_.NotifyObservers(func, render_frame_host, scope, allowed);
}

void WebContentsImpl::OnServiceWorkerAccessed(
    NavigationHandle* navigation,
    const GURL& scope,
    AllowServiceWorkerResult allowed) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::OnServiceWorkerAccessed",
                        "navigation_handle", navigation, "scope", scope);
  // Use a variable to select between overloads.
  void (WebContentsObserver::*func)(NavigationHandle*, const GURL&,
                                    AllowServiceWorkerResult) =
      &WebContentsObserver::OnServiceWorkerAccessed;
  observers_.NotifyObservers(func, navigation, scope, allowed);
}

void WebContentsImpl::OnColorChooserFactoryReceiver(
    mojo::PendingReceiver<blink::mojom::ColorChooserFactory> receiver) {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::OnColorChooserFactoryReceiver");
  color_chooser_factory_receivers_.Add(this, std::move(receiver));
}

#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
void WebContentsImpl::OpenColorChooser(
    mojo::PendingReceiver<blink::mojom::ColorChooser> chooser_receiver,
    mojo::PendingRemote<blink::mojom::ColorChooserClient> client,
    SkColor color,
    std::vector<blink::mojom::ColorSuggestionPtr> suggestions) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::OpenColorChooser");
  // Create `color_chooser_holder_` before calling OpenColorChooser since
  // OpenColorChooser may callback with results.
  color_chooser_holder_.reset();
  color_chooser_holder_ = std::make_unique<ColorChooserHolder>(
      std::move(chooser_receiver), std::move(client));

  auto new_color_chooser =
      delegate_ ? delegate_->OpenColorChooser(this, color, suggestions)
                : nullptr;
  if (color_chooser_holder_ && new_color_chooser) {
    color_chooser_holder_->SetChooser(std::move(new_color_chooser));
  } else if (new_color_chooser) {
    // OpenColorChooser synchronously called back to DidEndColorChooser.
    DCHECK(!color_chooser_holder_);
    new_color_chooser->End();
  } else if (color_chooser_holder_) {
    DCHECK(!new_color_chooser);
    color_chooser_holder_.reset();
  }
}
#endif  // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)

void WebContentsImpl::UpdateFaviconURL(
    RenderFrameHostImpl* source,
    const std::vector<blink::mojom::FaviconURLPtr>& candidates) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::UpdateFaviconURL",
                        "render_frame_host", source);
  // We get updated favicon URLs after the page stops loading. If a cross-site
  // navigation occurs while a page is still loading, the initial page
  // may stop loading and send us updated favicon URLs after the navigation
  // for the new page has committed.
  if (!source->IsInPrimaryMainFrame()) {
    return;
  }

  observers_.NotifyObservers(&WebContentsObserver::DidUpdateFaviconURL, source,
                             candidates);
}

void WebContentsImpl::SetIsOverlayContent(bool is_overlay_content) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::SetIsOverlayContent",
                        "is_overlay_content", is_overlay_content);
  is_overlay_content_ = is_overlay_content;
}

void WebContentsImpl::OnFirstVisuallyNonEmptyPaint(PageImpl& page) {
  OPTIONAL_TRACE_EVENT1(
      "content", "WebContentsImpl::OnFirstVisuallyNonEmptyPaint", "page", page);
  if (!page.IsPrimary()) {
    return;
  }

  {
    SCOPED_UMA_HISTOGRAM_TIMER(
        "WebContentsObserver.DidFirstVisuallyNonEmptyPaint");
    observers_.NotifyObservers(
        &WebContentsObserver::DidFirstVisuallyNonEmptyPaint);
  }
  if (page.theme_color() != last_sent_theme_color_) {
    // Theme color should have updated by now if there was one.
    observers_.NotifyObservers(&WebContentsObserver::DidChangeThemeColor);
    last_sent_theme_color_ = GetPrimaryPage().theme_color();
  }

  if (page.background_color() != last_sent_background_color_) {
    // Background color should have updated by now if there was one.
    observers_.NotifyObservers(&WebContentsObserver::OnBackgroundColorChanged);
    last_sent_background_color_ = page.background_color();
  }
#if BUILDFLAG(IS_ANDROID)
  if (base::FeatureList::IsEnabled(
          features::kAndroidWarmUpSpareRendererWithTimeout) &&
      features::kAndroidSpareRendererCreationTiming.Get() ==
          features::kAndroidSpareRendererCreationAfterFirstPaint) {
    WarmUpAndroidSpareRenderer();
  }
#endif
}

bool WebContentsImpl::IsGuest() {
  return !!browser_plugin_guest_;
}

void WebContentsImpl::NotifyBeforeFormRepostWarningShow() {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::NotifyBeforeFormRepostWarningShow");
  observers_.NotifyObservers(&WebContentsObserver::BeforeFormRepostWarningShow);
}

void WebContentsImpl::ActivateAndShowRepostFormWarningDialog() {
  OPTIONAL_TRACE_EVENT0(
      "content", "WebContentsImpl::ActivateAndShowRepostFormWarningDialog");
  Activate();
  if (delegate_) {
    delegate_->ShowRepostFormWarningDialog(this);
  }
}

bool WebContentsImpl::HasAccessedInitialDocument() {
  return GetPrimaryFrameTree().has_accessed_initial_main_document();
}

void WebContentsImpl::UpdateTitleForEntry(NavigationEntry* entry,
                                          const std::u16string& title) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::UpdateTitleForEntry",
                        "title", title);
  NavigationEntryImpl* entry_impl =
      NavigationEntryImpl::FromNavigationEntry(entry);
  bool title_changed = UpdateTitleForEntryImpl(entry_impl, title);
  if (title_changed) {
    NotifyTitleUpdateForEntry(entry_impl);
  }
}

bool WebContentsImpl::UpdateTitleForEntryImpl(NavigationEntryImpl* entry,
                                              const std::u16string& title) {
  DCHECK(entry);
  std::u16string final_title;
  base::TrimWhitespace(title, base::TRIM_ALL, &final_title);

  if (final_title == entry->GetTitle()) {
    return false;  // Nothing changed, don't bother.
  }

  entry->SetTitle(std::move(final_title));
  return true;
}

void WebContentsImpl::NotifyTitleUpdateForEntry(NavigationEntryImpl* entry) {
  // |entry| must belong to the primary frame tree's NavigationController.
  DCHECK(GetController().GetEntryWithUniqueIDIncludingPending(
      entry->GetUniqueID()));
  std::u16string final_title = entry->GetTitleForDisplay();
  bool did_web_contents_title_change = entry == GetNavigationEntryForTitle();
  if (did_web_contents_title_change) {
    view_->SetPageTitle(final_title);
  }

  {
    SCOPED_UMA_HISTOGRAM_TIMER("WebContentsObserver.TitleWasSet");
    observers_.NotifyObservers(&WebContentsObserver::TitleWasSet, entry);
  }

  if (did_web_contents_title_change) {
    NotifyNavigationStateChanged(INVALIDATE_TYPE_TITLE);
  }
}

NavigationEntry* WebContentsImpl::GetNavigationEntryForTitle() {
  // We use the title for the last committed entry rather than a pending
  // navigation entry. For example, when the user types in a URL, we want to
  // keep the old page's title until the new load has committed and we get a new
  // title.
  NavigationEntry* entry = GetController().GetLastCommittedEntry();

  // We make an exception for initial navigations. We only want to use the title
  // from the visible entry if:
  // 1. The pending entry has been explicitly assigned a title to display.
  // 2. The user is doing a history navigation in a new tab (e.g., Ctrl+Back),
  //    which case there is a pending entry index other than -1.
  //
  // Otherwise, we want to stick with the last committed entry's title during
  // new navigations, which have pending entries at index -1 with no title.
  if (GetController().IsInitialNavigation() &&
      ((GetController().GetVisibleEntry() &&
        !GetController().GetVisibleEntry()->GetTitle().empty()) ||
       GetController().GetPendingEntryIndex() != -1)) {
    entry = GetController().GetVisibleEntry();
  }

  return entry;
}

void WebContentsImpl::SendChangeLoadProgress() {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::SendChangeLoadProgress",
                        "load_progress", GetLoadProgress());
  loading_last_progress_update_ = base::TimeTicks::Now();

  SCOPED_UMA_HISTOGRAM_TIMER("WebContentsObserver.LoadProgressChanged");
  observers_.NotifyObservers(&WebContentsObserver::LoadProgressChanged,
                             GetLoadProgress());
}

void WebContentsImpl::ResetLoadProgressState() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::ResetLoadProgressState");
  GetPrimaryPage().set_load_progress(0.0);
  loading_weak_factory_.InvalidateWeakPtrs();
  loading_last_progress_update_ = base::TimeTicks();
}

// Notifies the RenderWidgetHost instance about the fact that the page is
// loading, or done loading.
void WebContentsImpl::LoadingStateChanged(LoadingState new_state) {
  if (IsBeingDestroyed()) {
    return;
  }

  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::LoadingStateChanged",
                        "loading_state", new_state);

  if (new_state == LoadingState::NONE) {
    load_state_ =
        net::LoadStateWithParam(net::LOAD_STATE_IDLE, std::u16string());
    load_state_host_.clear();
    upload_size_ = 0;
    upload_position_ = 0;
  }

  if (delegate_) {
    delegate_->LoadingStateChanged(
        this, new_state == LoadingState::LOADING_UI_REQUESTED);
  }
  NotifyNavigationStateChanged(INVALIDATE_TYPE_LOAD);
}

void WebContentsImpl::NotifyViewSwapped(RenderViewHost* old_view,
                                        RenderViewHost* new_view) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::NotifyViewSwapped",
                        "old_view", old_view, "new_view", new_view);
  DCHECK_NE(old_view, new_view);
  // After sending out a swap notification, we need to send a disconnect
  // notification so that clients that pick up a pointer to |this| can NULL the
  // pointer.  See Bug 1230284.
  notify_disconnection_ = true;
  observers_.NotifyObservers(&WebContentsObserver::RenderViewHostChanged,
                             old_view, new_view);
  view_->RenderViewHostChanged(old_view, new_view);

  // If this is an inner WebContents that has swapped views, we need to reattach
  // it to its outer WebContents.
  if (node_.outer_web_contents()) {
    ReattachToOuterWebContentsFrame();
  }

  // Ensure that the associated embedder gets cleared after a RenderViewHost
  // gets swapped, so we don't reuse the same embedder next time a
  // RenderViewHost is attached to this WebContents.
  RemoveBrowserPluginEmbedder();
}

void WebContentsImpl::NotifyFrameSwapped(RenderFrameHostImpl* old_frame,
                                         RenderFrameHostImpl* new_frame) {
  TRACE_EVENT2("content", "WebContentsImpl::NotifyFrameSwapped", "old_frame",
               old_frame, "new_frame", new_frame);
#if BUILDFLAG(IS_ANDROID)
  // Copy importance from |old_frame| if |new_frame| is a main frame.
  if (old_frame && !new_frame->GetParent()) {
    RenderWidgetHostImpl* old_widget = old_frame->GetRenderWidgetHost();
    RenderWidgetHostImpl* new_widget = new_frame->GetRenderWidgetHost();
    new_widget->SetImportance(old_widget->importance());
  }
#endif
  observers_.NotifyObservers(&WebContentsObserver::RenderFrameHostChanged,
                             old_frame, new_frame);
}

void WebContentsImpl::NotifyNavigationEntryCommitted(
    const LoadCommittedDetails& load_details) {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::NotifyNavigationEntryCommitted");
  SCOPED_UMA_HISTOGRAM_TIMER("WebContentsObserver.NavigationEntryCommitted");
  observers_.NotifyObservers(&WebContentsObserver::NavigationEntryCommitted,
                             load_details);
}

void WebContentsImpl::NotifyNavigationEntryChanged(
    const EntryChangedDetails& change_details) {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::NotifyNavigationEntryChanged");
  SCOPED_UMA_HISTOGRAM_TIMER("WebContentsObserver.NavigationEntryChanged");
  observers_.NotifyObservers(&WebContentsObserver::NavigationEntryChanged,
                             change_details);
}

void WebContentsImpl::NotifyNavigationListPruned(
    const PrunedDetails& pruned_details) {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::NotifyNavigationListPruned");
  observers_.NotifyObservers(&WebContentsObserver::NavigationListPruned,
                             pruned_details);
}

void WebContentsImpl::NotifyNavigationEntriesDeleted() {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::NotifyNavigationEntriesDeleted");
  SCOPED_UMA_HISTOGRAM_TIMER("WebContentsObserver.NavigationEntryDeleted");
  observers_.NotifyObservers(&WebContentsObserver::NavigationEntriesDeleted);
}

void WebContentsImpl::OnDidBlockNavigation(
    const GURL& blocked_url,
    const GURL& initiator_url,
    blink::mojom::NavigationBlockedReason reason) {
  OPTIONAL_TRACE_EVENT("content", "WebContentsImpl::OnDidBlockNavigation",
                       "blocked_url", blocked_url, "initiator_url",
                       initiator_url, "reason", reason);
  if (delegate_) {
    delegate_->OnDidBlockNavigation(this, blocked_url, reason);
  }
}

void WebContentsImpl::RenderFrameCreated(
    RenderFrameHostImpl* render_frame_host) {
  TRACE_EVENT1("content", "WebContentsImpl::RenderFrameCreated",
               "render_frame_host", render_frame_host);

  if (render_frame_host->IsInPrimaryMainFrame()) {
    NotifyPrimaryMainFrameProcessIsAlive();
  }

  {
    SCOPED_UMA_HISTOGRAM_TIMER("WebContentsObserver.RenderFrameCreated");
    observers_.NotifyObservers(&WebContentsObserver::RenderFrameCreated,
                               render_frame_host);
  }
  render_frame_host->UpdateAccessibilityMode();

  if (safe_area_insets_host_) {
    safe_area_insets_host_->RenderFrameCreated(render_frame_host);
  }

#if BUILDFLAG(IS_ANDROID)
  if (base::FeatureList::IsEnabled(features::kSubframeImportance) &&
      render_frame_host->GetParent() &&
      render_frame_host->frame_tree()->is_primary()) {
    if (auto* rwh = render_frame_host->GetLocalRenderWidgetHost()) {
      rwh->SetImportance(primary_subframe_importance_);
    }
  }
#endif
}

void WebContentsImpl::RenderFrameDeleted(
    RenderFrameHostImpl* render_frame_host) {
  TRACE_EVENT1("content", "WebContentsImpl::RenderFrameDeleted",
               "render_frame_host", render_frame_host);
  {
    SCOPED_UMA_HISTOGRAM_TIMER("WebContentsObserver.RenderFrameDeleted");
    observers_.NotifyObservers(&WebContentsObserver::RenderFrameDeleted,
                               render_frame_host);
  }

  if (safe_area_insets_host_) {
    safe_area_insets_host_->RenderFrameDeleted(render_frame_host);
  }

  // Remove any fullscreen state that the frame has stored.
  FullscreenStateChanged(render_frame_host, false /* is_fullscreen */,
                         blink::mojom::FullscreenOptionsPtr());
}

void WebContentsImpl::ShowContextMenu(
    RenderFrameHostImpl& render_frame_host,
    mojo::PendingAssociatedRemote<blink::mojom::ContextMenuClient>
        context_menu_client,
    const ContextMenuParams& params) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::ShowContextMenu",
                        "render_frame_host", render_frame_host);
  // If a renderer fires off a second command to show a context menu before the
  // first context menu is closed, just ignore it. https://crbug.com/707534
  if (showing_context_menu_) {
    return;
  }

  if (context_menu_client) {
    context_menu_client_.reset();
    context_menu_client_.Bind(std::move(context_menu_client));
  }

  ContextMenuParams context_menu_params(params);

  // Give guest a first crack at the context menu.
  if (GuestPageHolderImpl* guest_holder =
          GuestPageHolderImpl::FromRenderFrameHost(render_frame_host)) {
    if (auto* guest_delegate = guest_holder->delegate()) {
      if (guest_delegate->GuestHandleContextMenu(render_frame_host,
                                                 context_menu_params)) {
        return;
      }
    }
  }

  // Allow WebContentsDelegates to handle the context menu operation first.
  if (delegate_ &&
      delegate_->HandleContextMenu(render_frame_host, context_menu_params)) {
    return;
  }

  render_view_host_delegate_view_->ShowContextMenu(render_frame_host,
                                                   context_menu_params);
}

namespace {
// Normalizes the line endings: \r\n -> \n, lone \r -> \n.
std::u16string NormalizeLineBreaks(const std::u16string& source) {
  static const base::NoDestructor<std::u16string> kReturnNewline(u"\r\n");
  static const base::NoDestructor<std::u16string> kReturn(u"\r");
  static const base::NoDestructor<std::u16string> kNewline(u"\n");

  std::vector<std::u16string_view> pieces;

  for (const auto& rn_line : base::SplitStringPieceUsingSubstr(
           source, *kReturnNewline, base::KEEP_WHITESPACE,
           base::SPLIT_WANT_ALL)) {
    auto r_lines = base::SplitStringPieceUsingSubstr(
        rn_line, *kReturn, base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
    std::move(std::begin(r_lines), std::end(r_lines),
              std::back_inserter(pieces));
  }

  return base::JoinString(pieces, *kNewline);
}
}  // namespace

void WebContentsImpl::RunJavaScriptDialog(
    RenderFrameHostImpl* render_frame_host,
    const std::u16string& message,
    const std::u16string& default_prompt,
    JavaScriptDialogType dialog_type,
    bool disable_third_party_subframe_suppresion,
    JavaScriptDialogCallback response_callback) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::RunJavaScriptDialog",
                        "render_frame_host", render_frame_host);
  DCHECK(render_frame_host->IsActive());

  // Ensure that if showing a dialog is the first thing that a page does, that
  // the contents of the previous page aren't shown behind it. This is required
  // because showing a dialog freezes the renderer, so no frames will be coming
  // from it. https://crbug.com/823353
  auto* render_widget_host_impl = render_frame_host->GetRenderWidgetHost();
  if (render_widget_host_impl) {
    render_widget_host_impl->ForceFirstFrameAfterNavigationTimeout();
  }

  // Running a dialog causes an exit to webpage-initiated fullscreen.
  // http://crbug.com/728276
  base::ScopedClosureRunner fullscreen_block =
      ForSecurityDropFullscreen(/*display_id=*/display::kInvalidDisplayId);

  auto callback = base::BindOnce(
      &WebContentsImpl::OnDialogClosed, weak_factory_.GetWeakPtr(),
      render_frame_host->GetProcess()->GetDeprecatedID(),
      render_frame_host->GetRoutingID(), std::move(response_callback),
      std::move(fullscreen_block));

  std::vector<protocol::PageHandler*> page_handlers =
      protocol::PageHandler::EnabledForWebContents(this);

  bool should_suppress = false;
  JavaScriptDialogManager* dialog_manager = nullptr;
  // Give guest a first crack at the dialog.
  if (GuestPageHolderImpl* guest_holder =
          GuestPageHolderImpl::FromRenderFrameHost(*render_frame_host)) {
    if (auto* guest_delegate = guest_holder->delegate()) {
      dialog_manager = guest_delegate->GuestGetJavascriptDialogManager();
    }
  } else if (delegate_) {
    dialog_manager = delegate_->GetJavaScriptDialogManager(this);
    should_suppress = delegate_->ShouldSuppressDialogs(this);
  }

  // While a JS message dialog is showing, defer commits in this WebContents.
  javascript_dialog_dismiss_notifier_ =
      std::make_unique<JavaScriptDialogDismissNotifier>();

  // Suppress JavaScript dialogs when requested.
  bool has_non_devtools_handlers = delegate_ && dialog_manager;
  bool has_handlers = page_handlers.size() || has_non_devtools_handlers;
  bool suppress_this_message = should_suppress || !has_handlers;

  if (!disable_third_party_subframe_suppresion &&
      GetContentClient()->browser()->SuppressDifferentOriginSubframeJSDialogs(
          GetBrowserContext())) {
    // We can't check for opaque origin cases, default to allowing them to
    // trigger dialogs.
    // TODO(carlosil): The main use case for opaque use cases are tests,
    // investigate if there are uses in the wild, otherwise adapt tests that
    // require dialogs so they commit an origin first, and remove this
    // conditional.
    if (!render_frame_host->GetLastCommittedOrigin().opaque()) {
      bool is_different_origin_subframe =
          render_frame_host->GetLastCommittedOrigin() !=
          render_frame_host->GetOutermostMainFrame()->GetLastCommittedOrigin();
      suppress_this_message |= is_different_origin_subframe;
      if (is_different_origin_subframe) {
        GetPrimaryMainFrame()->AddMessageToConsole(
            blink::mojom::ConsoleMessageLevel::kWarning,
            base::StringPrintf(
                "A different origin subframe tried to create a JavaScript "
                "dialog. This is no longer allowed and was blocked. See "
                "https://www.chromestatus.com/feature/5148698084376576 for "
                "more details."));
      }
    }
  }

  if (suppress_this_message) {
    std::move(callback).Run(true, false, std::u16string());
    return;
  }

  scoped_refptr<CloseDialogCallbackWrapper> wrapper =
      new CloseDialogCallbackWrapper(std::move(callback));

  is_showing_javascript_dialog_ = true;

  std::u16string normalized_message = NormalizeLineBreaks(message);

  for (auto* handler : page_handlers) {
    handler->DidRunJavaScriptDialog(
        render_frame_host->GetLastCommittedURL(),
        render_frame_host->devtools_frame_token(), normalized_message,
        default_prompt, dialog_type, has_non_devtools_handlers,
        base::BindOnce(&CloseDialogCallbackWrapper::Run, wrapper, false));
  }

  if (dialog_manager) {
    created_dialog_since_last_cancel_ = true;
    dialog_manager->RunJavaScriptDialog(
        this, render_frame_host, dialog_type, normalized_message,
        default_prompt,
        base::BindOnce(&CloseDialogCallbackWrapper::Run, wrapper, false),
        &suppress_this_message);
  }

  if (suppress_this_message) {
    // If we are suppressing messages, just reply as if the user immediately
    // pressed "Cancel", passing true to |dialog_was_suppressed|.
    wrapper->Run(true, false, std::u16string());
  }
}

void WebContentsImpl::NotifyOnJavaScriptDialogDismiss(
    base::OnceClosure callback) {
  DCHECK(javascript_dialog_dismiss_notifier_);
  javascript_dialog_dismiss_notifier_->NotifyOnDismiss(std::move(callback));
}

void WebContentsImpl::Close(RenderFrameHostImpl* render_frame_host) {
  if (GuestPageHolderImpl* guest_holder =
          GuestPageHolderImpl::FromRenderFrameHost(*render_frame_host)) {
    if (auto* guest_delegate = guest_holder->delegate()) {
      guest_delegate->GuestClose();
    }
    return;
  }
  Close();
}

void WebContentsImpl::RunBeforeUnloadConfirm(
    RenderFrameHostImpl* render_frame_host,
    bool is_reload,
    JavaScriptDialogCallback response_callback) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::RunBeforeUnloadConfirm",
                        "render_frame_host", render_frame_host, "is_reload",
                        is_reload);
  DCHECK(render_frame_host->IsActive());

  // Ensure that if showing a dialog is the first thing that a page does, that
  // the contents of the previous page aren't shown behind it. This is required
  // because showing a dialog freezes the renderer, so no frames will be coming
  // from it. https://crbug.com/823353
  auto* render_widget_host_impl = render_frame_host->GetRenderWidgetHost();
  if (render_widget_host_impl) {
    render_widget_host_impl->ForceFirstFrameAfterNavigationTimeout();
  }

  // Running a dialog causes an exit to webpage-initiated fullscreen.
  // http://crbug.com/728276
  base::ScopedClosureRunner fullscreen_block =
      ForSecurityDropFullscreen(/*display_id=*/display::kInvalidDisplayId);

  auto callback = base::BindOnce(
      &WebContentsImpl::OnDialogClosed, weak_factory_.GetWeakPtr(),
      render_frame_host->GetProcess()->GetDeprecatedID(),
      render_frame_host->GetRoutingID(), std::move(response_callback),
      std::move(fullscreen_block));

  std::vector<protocol::PageHandler*> page_handlers =
      protocol::PageHandler::EnabledForWebContents(this);

  JavaScriptDialogManager* dialog_manager = nullptr;
  bool should_suppress = false;
  // Give guest a first crack at the dialog.
  if (GuestPageHolderImpl* guest_holder =
          GuestPageHolderImpl::FromRenderFrameHost(*render_frame_host)) {
    if (auto* guest_delegate = guest_holder->delegate()) {
      dialog_manager = guest_delegate->GuestGetJavascriptDialogManager();
    }
  } else if (delegate_) {
    dialog_manager = delegate_->GetJavaScriptDialogManager(this);
    should_suppress = delegate_->ShouldSuppressDialogs(this);
  }

  // While a JS beforeunload dialog is showing, defer commits in this
  // WebContents.
  javascript_dialog_dismiss_notifier_ =
      std::make_unique<JavaScriptDialogDismissNotifier>();

  bool has_non_devtools_handlers = delegate_ && dialog_manager;
  bool has_handlers = page_handlers.size() || has_non_devtools_handlers;
  if (should_suppress || !has_handlers) {
    std::move(callback).Run(false, true, std::u16string());
    return;
  }

  is_showing_before_unload_dialog_ = true;

  scoped_refptr<CloseDialogCallbackWrapper> wrapper =
      new CloseDialogCallbackWrapper(std::move(callback));

  GURL frame_url = render_frame_host->GetLastCommittedURL();
  for (auto* handler : page_handlers) {
    handler->DidRunBeforeUnloadConfirm(
        frame_url, render_frame_host->devtools_frame_token(),
        has_non_devtools_handlers,
        base::BindOnce(&CloseDialogCallbackWrapper::Run, wrapper, false));
  }

  if (dialog_manager) {
    created_dialog_since_last_cancel_ = true;
    dialog_manager->RunBeforeUnloadDialog(
        this, render_frame_host, is_reload,
        base::BindOnce(&CloseDialogCallbackWrapper::Run, wrapper, false));
#if BUILDFLAG(IS_ANDROID)
    // If A embeds a subframe B and B has a BeforeUnload handler whereas A
    // doesn't, the main frame navigation from A will show a dialog. In that
    // case `render_frame_host` is B and `initiator` is A. The navigation
    // request is on A.
    RenderFrameHostImpl* initiator =
        render_frame_host->GetBeforeUnloadInitiator();
    NavigationRequest* request =
        initiator ? initiator->frame_tree_node()->navigation_request()
                  : nullptr;
    auto* animation_manager =
        static_cast<BackForwardTransitionAnimationManagerAndroid*>(
            GetBackForwardTransitionAnimationManager());
    // We might not always have a NavigationRequest at this point (i.e. a
    // renderer-initiated navigation). However if this is a browser-initiated
    // history navigation, the request can't be null.
    if (animation_manager && request) {
      animation_manager->OnBeforeUnloadDialogShown(request->GetNavigationId());
    }
#endif
  }
}

void WebContentsImpl::RunFileChooser(
    base::WeakPtr<FileChooserImpl> file_chooser,
    RenderFrameHost* render_frame_host,
    scoped_refptr<FileChooserImpl::FileSelectListenerImpl> listener,
    const blink::mojom::FileChooserParams& params) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::RunFileChooser",
                        "render_frame_host", render_frame_host);

  absl::Cleanup cancel_chooser = [&listener] {
    listener->FileSelectionCanceled();
  };
  if (visibility_ == Visibility::HIDDEN) {
    // Do not allow background tab to open file chooser.
    return;
  }
  if (!delegate_->IsContentsActive(this)) {
    // Do not allow inactive tabs to open file chooser.
    return;
  }
  if (active_file_chooser_) {
    // Only allow one active file chooser at one time.
    return;
  }

  // Any explicit focusing of another window while this WebContents is in
  // fullscreen can be used to confuse the user, so drop fullscreen.
  base::ScopedClosureRunner fullscreen_block =
      ForSecurityDropFullscreen(/*display_id=*/display::kInvalidDisplayId);
  listener->SetFullscreenBlock(std::move(fullscreen_block));

  if (delegate_) {
    active_file_chooser_ = std::move(file_chooser);
    delegate_->RunFileChooser(render_frame_host, std::move(listener), params);
    std::move(cancel_chooser).Cancel();
  }
}

double WebContentsImpl::GetPendingZoomLevel(RenderWidgetHostImpl* rwh) {
  RenderFrameHostImpl* rfh = nullptr;
  // Find the RenderFrameHost for `rwh`.
  ForEachRenderFrameHostImplWithAction(
      [rwh, &rfh](RenderFrameHostImpl* render_frame_host) {
        if (render_frame_host->GetRenderWidgetHost() == rwh) {
          rfh = render_frame_host;
          return RenderFrameHost::FrameIterationAction::kStop;
        }
        return RenderFrameHost::FrameIterationAction::kContinue;
      });

  if (rfh) {
    // Find nearest ancestor that has independent zoom.
    // Use GetParentOrOuterDocument() instead of GetParent() in order
    // to "step out of" any fenced frames that are encountered.
    while (!HostZoomMapForRenderFrameHost(rfh)->IsIndependentZoomFrameTreeNode(
               rfh->GetFrameTreeNodeId()) &&
           rfh->GetParentOrOuterDocument()) {
      rfh = rfh->GetParentOrOuterDocument();
    }
  } else {
    // Not finding a `rfh` suggests that `rwh` is still in the process of being
    // set up, or is for a newly created RenderWidgetHost without a
    // RenderFrameHost (e.g. for a <select> tag popup>), and that this function
    // will be called again when there is a findable `rfh` for `rwh`. For now,
    // just return the zoom level of this WebContents, as that will most often
    // be right.
    return HostZoomMap::GetZoomLevel(this);
  }

  GURL url;
  if (rfh->IsInBackForwardCache()) {
    // If the `rfh`s page is in the bf cache, then the use of the pending (or
    // last committed) entry would have the lookup be based on an unrelated URL.
    // In that case use the RFH's last committed URL. While using the
    // NavigationEntry is preferred in order to avoid a virtual URL, that
    // shouldn't be a problem if the URL from the `rfh` is used. Note that
    // subframes get their zoom updates asynchronously from the main frame, so
    // it's possible to get here in a race condition for a page that is no
    // longer visible. For example, it's possible to get here on Android in the
    // tests FencedFrameParameterizedBrowserTest.NavigateUnfencedTopAndGoBack
    // and All/FencedFrameAutomaticBeaconBrowserTest.MessageExceedsLengthLimit/
    // fencedframe.
    url = rfh->GetLastCommittedURL();
  } else if (!rfh->GetParent()) {
    // Only use the pending entry if `rfh` is a main frame, otherwise the
    // resulting url is from outside the independently zoomed subtree, and
    // may result in the wrong zoom level.
    NavigationEntry* pending_entry = rfh->GetController().GetPendingEntry();
    if (!pending_entry) {
      return HostZoomMap::GetZoomLevel(this, rfh->GetGlobalId());
    }
    url = pending_entry->GetURL();
  } else {
    // In this case `rfh` is for an independently-zoomed subframe. Call
    // GetZoomLevel(WebContents*, RenderFrameHost*) in case `rfh` uses temporary
    // zoom.
    return HostZoomMap::GetZoomLevel(this, rfh->GetGlobalId());
  }
#if BUILDFLAG(IS_ANDROID)
  return HostZoomMapForRenderFrameHost(rfh)
      ->GetZoomLevelForHostAndSchemeAndroid(url.GetScheme(),
                                            net::GetHostOrSpecFromURL(url));
#else
  return HostZoomMapForRenderFrameHost(rfh)->GetZoomLevelForHostAndScheme(
      url.GetScheme(), net::GetHostOrSpecFromURL(url));
#endif
}

bool WebContentsImpl::IsPictureInPictureAllowedForFullscreenVideo() const {
  return media_web_contents_observer_
      ->IsPictureInPictureAllowedForFullscreenVideo();
}

bool WebContentsImpl::IsFocusedElementEditable() {
  RenderFrameHostImpl* frame = GetFocusedFrame();
  return frame && frame->has_focused_editable_element();
}

bool WebContentsImpl::IsShowingContextMenu() {
  return showing_context_menu_;
}

void WebContentsImpl::SetShowingContextMenu(bool showing) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::SetShowingContextMenu",
                        "showing", showing);

  DCHECK_NE(showing_context_menu_, showing);
  showing_context_menu_ = showing;

  if (auto* view = GetRenderWidgetHostView()) {
    // Notify the main frame's RWHV to run the platform-specific code, if any.
    static_cast<RenderWidgetHostViewBase*>(view)->SetShowingContextMenu(
        showing);
  }
}

void WebContentsImpl::ClearFocusedElement() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::ClearFocusedElement");
  if (auto* frame = GetFocusedFrame()) {
    frame->ClearFocusedElement();
  }
}

bool WebContentsImpl::IsNeverComposited() {
  return is_never_composited_;
}

RenderViewHostDelegateView* WebContentsImpl::GetDelegateView() {
  return render_view_host_delegate_view_;
}

const blink::RendererPreferences& WebContentsImpl::GetRendererPrefs(
    RenderViewHostImpl* render_view_host) {
  if (auto* guest = GuestPageHolderImpl::FromRenderFrameHost(
          *render_view_host->frame_tree()->GetMainFrame())) {
    return guest->GetRendererPrefs();
  }
  RenderViewHostImpl::GetPlatformSpecificPrefs(&renderer_preferences_);
  return renderer_preferences_;
}

const blink::web_pref::WebPreferences&
WebContentsImpl::GetOrCreateWebPreferences(
    RenderViewHostImpl* render_view_host) {
  if (auto* guest = GuestPageHolderImpl::FromRenderFrameHost(
          *render_view_host->frame_tree()->GetMainFrame())) {
    return guest->GetWebPreferences();
  }
  return GetOrCreateWebPreferences();
}

RenderFrameHostImpl* WebContentsImpl::GetOuterWebContentsFrame() {
  if (GetOuterDelegateFrameTreeNodeId().is_null()) {
    return nullptr;
  }

  FrameTreeNode* outer_node =
      FrameTreeNode::GloballyFindByID(GetOuterDelegateFrameTreeNodeId());
  // The outer node should be in the outer WebContents.
  DCHECK_EQ(&outer_node->frame_tree(),
            &GetOuterWebContents()->GetPrimaryFrameTree());
  return outer_node->parent();
}

WebContentsImpl* WebContentsImpl::GetOuterWebContents() {
  return node_.outer_web_contents();
}

std::vector<WebContents*> WebContentsImpl::GetInnerWebContents() {
  std::vector<WebContents*> all_inner_contents;
  const auto& inner_contents = node_.GetInnerWebContents();
  all_inner_contents.insert(all_inner_contents.end(), inner_contents.begin(),
                            inner_contents.end());
  return all_inner_contents;
}

WebContentsImpl* WebContentsImpl::GetResponsibleWebContents() {
  if (delegate_) {
    WebContentsImpl* responsible_from_delegate = static_cast<WebContentsImpl*>(
        delegate_->GetResponsibleWebContents(this));
    if (responsible_from_delegate) {
      return responsible_from_delegate;
    }
  }

  return FromRenderFrameHostImpl(
      GetPrimaryMainFrame()->GetOutermostMainFrameOrEmbedder());
}

WebContentsImpl* WebContentsImpl::GetFocusedWebContents() {
  return WebContentsImpl::FromFrameTreeNode(GetFocusedFrameTree()->root());
}

FrameTree* WebContentsImpl::GetFocusedFrameTree() {
  return GetOutermostWebContents()->node_.focused_frame_tree();
}

void WebContentsImpl::SetFocusToLocationBar() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::SetFocusToLocationBar");
  if (delegate_) {
    delegate_->SetFocusToLocationBar();
  }
}

bool WebContentsImpl::ContainsOrIsFocusedWebContents() {
  for (WebContentsImpl* focused_contents = GetFocusedWebContents();
       focused_contents;
       focused_contents = focused_contents->GetOuterWebContents()) {
    if (focused_contents == this) {
      return true;
    }
  }

  return false;
}

void WebContentsImpl::RemoveBrowserPluginEmbedder() {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::RemoveBrowserPluginEmbedder");
  browser_plugin_embedder_.reset();
}

WebContentsImpl* WebContentsImpl::GetOutermostWebContents() {
  WebContentsImpl* root = this;
  while (root->GetOuterWebContents()) {
    root = root->GetOuterWebContents();
  }
  return root;
}

void WebContentsImpl::InnerWebContentsCreated(WebContents* inner_web_contents) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::InnerWebContentsCreated");
  observers_.NotifyObservers(&WebContentsObserver::InnerWebContentsCreated,
                             inner_web_contents);
}

void WebContentsImpl::InnerWebContentsAttached(
    WebContents* inner_web_contents) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::InnerWebContentsAttached");
  if (inner_web_contents->IsCurrentlyAudible()) {
    OnAudioStateChanged();
  }
}

void WebContentsImpl::InnerWebContentsDetached(
    WebContents* inner_web_contents) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::InnerWebContentsDetached");
  if (!IsBeingDestroyed()) {
    OnAudioStateChanged();
  }
}

void WebContentsImpl::RenderViewReady(RenderViewHost* rvh) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::RenderViewReady",
                        "render_view_host", rvh);
  if (rvh != GetRenderViewHost()) {
    // Don't notify the world, since this came from a renderer in the
    // background.
    return;
  }

  RenderWidgetHostViewBase* rwhv =
      static_cast<RenderWidgetHostViewBase*>(GetRenderWidgetHostView());
  if (rwhv) {
    rwhv->SetMainFrameAXTreeID(GetPrimaryMainFrame()->GetAXTreeID());
  }

  notify_disconnection_ = true;

  {
    SCOPED_UMA_HISTOGRAM_TIMER("WebContentsObserver.RenderViewReady");
    observers_.NotifyObservers(&WebContentsObserver::RenderViewReady);
  }
  view_->RenderViewReady();
}

void WebContentsImpl::RenderViewTerminated(RenderViewHost* rvh,
                                           base::TerminationStatus status,
                                           int error_code) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::RenderViewTerminated",
                        "render_view_host", rvh, "status",
                        static_cast<int>(status));

  // It is possible to get here while the WebContentsImpl is being destroyed,
  // in particular when the destruction of the main frame's RenderFrameHost and
  // RenderViewHost triggers cleanup of the main frame's process, which in turn
  // dispatches RenderProcessExited observers, one of which calls in here.  In
  // this state, we cannot check GetRenderViewHost() below, since
  // current_frame_host() for the root FrameTreeNode has already been cleared.
  // Since the WebContents is going away, none of the work here is needed, so
  // just return early.
  auto* rvh_impl = static_cast<RenderViewHostImpl*>(rvh);
  if (IsBeingDestroyed() || rvh_impl->frame_tree()->IsBeingDestroyed()) {
    return;
  }

  // If we are a guest frame tree and the RenderViewHost is the main frame's RVH
  // then notify that the guest's main frame process went away.
  if (rvh_impl->frame_tree()->is_guest() &&
      rvh_impl->frame_tree()->GetMainFrame()->render_view_host() == rvh_impl) {
    if (auto* guest = GuestPageHolderImpl::FromRenderFrameHost(
            *rvh_impl->frame_tree()->GetMainFrame())) {
      guest->delegate()->GuestMainFrameProcessGone(status);
      return;
    }
  }

  if (rvh != GetRenderViewHost()) {
    // The pending page's RenderViewHost is gone.
    return;
  }

  DCHECK(rvh_impl->GetMainRenderFrameHost()->IsInPrimaryMainFrame())
      << "GetRenderViewHost() must belong to the primary frame tree";

  // Ensure fullscreen mode is exited in the |delegate_| since a crashed
  // renderer may not have made a clean exit.
  if (IsFullscreen()) {
    ExitFullscreenMode(false);
  }

  // Ensure any video or document in Picture-in-Picture is exited in the
  // |delegate_| since a crashed renderer may not have made a clean exit.
  if (HasPictureInPictureVideo() || HasPictureInPictureDocument()) {
    ExitPictureInPicture();
  }

  // Cancel any visible dialogs so they are not left dangling over the sad tab.
  CancelActiveAndPendingDialogs();

  audio_stream_monitor_.RenderProcessGone(
      rvh_impl->GetProcess()->GetDeprecatedID());

  // Reset the loading progress. TODO(avi): What does it mean to have a
  // "renderer crash" when there is more than one renderer process serving a
  // webpage? Once this function is called at a more granular frame level, we
  // probably will need to more granularly reset the state here.
  ResetLoadProgressState();

  SetPrimaryMainFrameProcessStatus(status, error_code);

  TRACE_EVENT0(
      "content",
      "Dispatching WebContentsObserver::PrimaryMainFrameRenderProcessGone");
  // Some observers might destroy WebContents in
  // PrimaryMainFrameRenderProcessGone.
  base::WeakPtr<WebContentsImpl> weak_ptr = weak_factory_.GetWeakPtr();
  for (auto& observer : observers_.observer_list()) {
    observer.PrimaryMainFrameRenderProcessGone(status);
    if (!weak_ptr) {
      return;
    }
  }

  // |this| might have been deleted. Do not add code here.
}

void WebContentsImpl::RenderViewDeleted(RenderViewHost* rvh) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::RenderViewDeleted",
                        "render_view_host", rvh);
  observers_.NotifyObservers(&WebContentsObserver::RenderViewDeleted, rvh);
}

void WebContentsImpl::ClearTargetURL() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::ClearTargetURL");
  frame_that_set_last_target_url_ = nullptr;
  if (delegate_) {
    delegate_->UpdateTargetURL(this, GURL());
  }
}

void WebContentsImpl::Close() {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::Close",
                        "render_frame_host", GetPrimaryMainFrame());
#if BUILDFLAG(IS_MAC)
  // The UI may be in an event-tracking loop, such as between the
  // mouse-down and mouse-up in text selection or a button click.
  // Defer the close until after tracking is complete, so that we
  // don't free objects out from under the UI.
  // TODO(shess): This could get more fine-grained.  For instance,
  // closing a tab in another window while selecting text in the
  // current window's Omnibox should be just fine.
  if (view_->CloseTabAfterEventTrackingIfNeeded()) {
    return;
  }
#endif

  if (delegate_) {
    delegate_->CloseContents(this);
  }
}

void WebContentsImpl::SetWindowRect(const gfx::Rect& new_bounds) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::SetWindowRect");
  if (!delegate_) {
    return;
  }

  // Members of |new_bounds| may be 0 to indicate uninitialized values for newly
  // opened windows, even if the |GetContainerBounds()| inner rect is correct.
  // TODO(crbug.com/40092782): Plumb values as specified; fallback on outer
  // rect.
  auto bounds = new_bounds;
  if (bounds.IsEmpty()) {
    bounds.set_size(GetContainerBounds().size());
  }

  // Only requests from the main frame, not subframes, should reach this code.
  int64_t display_id = AdjustWindowRect(&bounds, GetPrimaryMainFrame());

  // Drop fullscreen when placing a WebContents to prohibit deceptive behavior.
  // Only drop fullscreen on the specific destination display, which is known.
  // This supports sites using cross-screen window management capabilities to
  // retain fullscreen and place a window on another screen.
  ForSecurityDropFullscreen(display_id).RunAndReset();

  delegate_->SetContentsBounds(this, bounds);
}

void WebContentsImpl::UpdateWindowPreferredSize(
    RenderFrameHostImpl* render_frame_host,
    const gfx::Size& pref_size) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::UpdatePreferredSize");
  if (auto* guest =
          GuestPageHolderImpl::FromRenderFrameHost(*render_frame_host)) {
    guest->delegate()->GuestUpdateWindowPreferredSize(pref_size);
    return;
  }

  CHECK(render_frame_host->IsInPrimaryMainFrame());

  const gfx::Size old_size = GetPreferredSize();
  preferred_size_ = pref_size;
  OnPreferredSizeChanged(old_size);
}

std::vector<RenderFrameHostImpl*>
WebContentsImpl::GetActiveTopLevelDocumentsInBrowsingContextGroup(
    RenderFrameHostImpl* render_frame_host) {
  std::vector<RenderFrameHostImpl*> out;
  for (WebContentsImpl* web_contents : GetAllWebContents()) {
    RenderFrameHostImpl* other_render_frame_host =
        web_contents->GetPrimaryMainFrame();

    // Filters out inactive documents.
    if (other_render_frame_host->lifecycle_state() !=
        RenderFrameHostImpl::LifecycleStateImpl::kActive) {
      continue;
    }

    // Filter frames in different browsing context groups.
    if (!render_frame_host->GetSiteInstance()->IsRelatedSiteInstance(
            other_render_frame_host->GetSiteInstance())) {
      continue;
    }

    out.push_back(other_render_frame_host);
  }
  return out;
}

PrerenderHostRegistry* WebContentsImpl::GetPrerenderHostRegistry() {
  DCHECK(prerender_host_registry_);
  return prerender_host_registry_.get();
}

void WebContentsImpl::DidStartLoading(FrameTreeNode* frame_tree_node) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::DidStartLoading",
                        "frame_tree_node", frame_tree_node);

  TRACE_EVENT_BEGIN("browser,navigation", "WebContentsImpl Loading",
                    perfetto::Track::FromPointer(this), "URL", "NULL",
                    "Primary Main FrameTreeNode id",
                    GetPrimaryFrameTree().root()->frame_tree_node_id());
  SCOPED_UMA_HISTOGRAM_TIMER("WebContentsObserver.DidStartLoading");
  observers_.NotifyObservers(&WebContentsObserver::DidStartLoading);

  // Reset the focus state from DidStartNavigation to false if a new load starts
  // afterward, in case loading logic triggers a FocusLocationBarByDefault call.
  should_focus_location_bar_by_default_ = false;

  // Notify accessibility that the user is navigating away from the
  // current document.
  // TODO(domfarolino, dmazzoni): Do this using WebContentsObserver. See
  // https://crbug.com/981271.
  ui::BrowserAccessibilityManager* manager =
      frame_tree_node->current_frame_host()->browser_accessibility_manager();
  if (manager) {
    manager->UserIsNavigatingAway();
  }
}

void WebContentsImpl::DidStopLoading() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::DidStopLoading");
  if (IsBeingDestroyed()) {
    return;
  }

  // Use the last committed entry rather than the active one, in case a
  // pending entry has been created.
  // An entry may not exist for a stop when loading an initial blank page or
  // if an iframe injected by script into a blank page finishes loading.
  NavigationEntry* entry = GetController().GetLastCommittedEntry();
  std::string url =
      (entry ? entry->GetVirtualURL().possibly_invalid_spec() : "NULL");

  // WebContentsImpl Loading
  TRACE_EVENT_END("browser,navigation", perfetto::Track::FromPointer(this),
                  "URL", url);
  SCOPED_UMA_HISTOGRAM_TIMER("WebContentsObserver.DidStopLoading");
  observers_.NotifyObservers(&WebContentsObserver::DidStopLoading);

  GetPrimaryMainFrame()->ForEachRenderFrameHostImpl(
      [](RenderFrameHostImpl* render_frame_host) {
        ui::BrowserAccessibilityManager* manager =
            render_frame_host->browser_accessibility_manager();
        if (manager) {
          manager->DidStopLoading();
        }
      });

#if BUILDFLAG(IS_ANDROID)
  if (base::FeatureList::IsEnabled(
          features::kAndroidWarmUpSpareRendererWithTimeout) &&
      features::kAndroidSpareRendererCreationTiming.Get() ==
          features::kAndroidSpareRendererCreationAfterLoading) {
    WarmUpAndroidSpareRenderer();
  }
#endif
}

ui::AXTreeUpdate WebContentsImpl::RequestAXTreeSnapshotWithinBrowserProcess() {
  ui::BrowserAccessibilityManager* root_manager =
      GetRootBrowserAccessibilityManager();
  // A page can be fully loaded before a user turns on accessibility services,
  // and we can be in a transient state waiting for managers.
  if (!root_manager || !root_manager->ax_tree()) {
    return ui::AXTreeUpdate();
  }

  ui::AXTreeUpdate combined_update;
  ui::AXTreeCombiner combiner;

  GetPrimaryMainFrame()->ForEachRenderFrameHostImplWithAction(
      [this, &combiner](RenderFrameHostImpl* rfhi) {
        ui::BrowserAccessibilityManager* manager =
            rfhi->browser_accessibility_manager();
        if (!manager) {
          return RenderFrameHost::FrameIterationAction::kContinue;
        }

        ui::AXTree* tree = manager->ax_tree();
        if (!tree || !tree->root()) {
          return RenderFrameHost::FrameIterationAction::kContinue;
        }

        ui::AXTreeUpdate update_for_frame;
        update_for_frame.root_id = tree->root()->id();
        update_for_frame.tree_data = tree->data();

        std::vector<ui::AXNodeData> nodes;
        RecursivelyConstructAXTree(tree->root(), nodes);
        update_for_frame.nodes = nodes;

        combiner.AddTree(update_for_frame, rfhi->AccessibilityIsRootFrame());

        return RenderFrameHost::FrameIterationAction::kContinue;
      });

  // Combine all the individual frame tree updates into one.
  combiner.Combine();
  CHECK(combiner.combined());
  combined_update = std::move(combiner.combined().value());
  return combined_update;
}

void WebContentsImpl::RecursivelyConstructAXTree(
    ui::AXNode* node,
    std::vector<ui::AXNodeData>& nodes) {
  nodes.push_back(node->data());

  for (ui::AXNode* child : node->GetAllChildren()) {
    RecursivelyConstructAXTree(child, nodes);
  }
}

void WebContentsImpl::ApplyAXTreeFixingResult(ui::AXTreeID tree_id,
                                              ui::AXNodeID node_id,
                                              ax::mojom::Role role) {
// The AXTreeFixing feature is not currently available on Android.
#if !BUILDFLAG(IS_ANDROID)
  CHECK(features::IsAXTreeFixingEnabled());

  GetPrimaryMainFrame()->ForEachRenderFrameHostImplWithAction(
      [tree_id, node_id, role](RenderFrameHostImpl* rfhi) {
        ui::BrowserAccessibilityManager* manager =
            rfhi->browser_accessibility_manager();
        if (!manager) {
          return RenderFrameHost::FrameIterationAction::kContinue;
        }

        ui::AXTree* tree = manager->ax_tree();
        if (!tree || !tree->root()) {
          return RenderFrameHost::FrameIterationAction::kContinue;
        }

        ui::AXNode* node = manager->ax_tree()->GetFromId(node_id);
        if (!node) {
          return RenderFrameHost::FrameIterationAction::kContinue;
        }

        // Update the node's role and stop iterating.
        ui::AXNodeData new_data = node->data();
        new_data.role = role;
        node->SetData(new_data);
        return RenderFrameHost::FrameIterationAction::kStop;
      });
#endif
}

void WebContentsImpl::DidChangeLoadProgressForMainFrame(
    RenderFrameHostImpl* render_frame_host) {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::DidChangeLoadProgressForMainFrame");
  if (IsBeingDestroyed() ||
      render_frame_host->frame_tree()->IsBeingDestroyed()) {
    return;
  }

  DCHECK(render_frame_host->is_main_frame());
  if (!render_frame_host->IsOutermostMainFrame()) {
    // If this main frame isn't an outermost main frame but an embedded
    // main frame then return. ie. a fenced frame inside a guest.
    return;
  }

  if (auto* guest =
          GuestPageHolderImpl::FromRenderFrameHost(*render_frame_host)) {
    guest->delegate()->GuestDidChangeLoadProgress(
        render_frame_host->frame_tree()->GetLoadProgress());
  } else if (render_frame_host->IsInPrimaryMainFrame()) {
    double load_progress = GetLoadProgress();

    // The delegate is notified immediately for the first and last updates.
    // Also, since the message loop may be pretty busy when a page is loaded, it
    // might not execute a posted task in a timely manner so the progress report
    // is sent immediately if enough time has passed.
    base::TimeDelta min_delay = minimum_delay_between_loading_updates_ms_;
    bool delay_elapsed =
        loading_last_progress_update_.is_null() ||
        base::TimeTicks::Now() - loading_last_progress_update_ > min_delay;

    if (load_progress == 0.0 || load_progress == 1.0 || delay_elapsed) {
      // If there is a pending task to send progress, it is now obsolete.
      loading_weak_factory_.InvalidateWeakPtrs();

      // Notify the load progress change.
      SendChangeLoadProgress();

      // Clean-up the states if needed.
      if (load_progress == 1.0) {
        ResetLoadProgressState();
      }
      return;
    }

    if (loading_weak_factory_.HasWeakPtrs()) {
      return;
    }

    if (min_delay == base::Milliseconds(0)) {
      SendChangeLoadProgress();
    } else {
      base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
          FROM_HERE,
          base::BindOnce(&WebContentsImpl::SendChangeLoadProgress,
                         loading_weak_factory_.GetWeakPtr()),
          min_delay);
    }
  }
}

bool WebContentsImpl::IsHidden() {
  return GetPageVisibilityState() == PageVisibilityState::kHidden;
}

void WebContentsImpl::CreateThrottlesForNavigation(
    NavigationThrottleRegistry& registry) {
  OPTIONAL_TRACE_EVENT1("content",
                        "WebContentsImpl::CreateThrottlesForNavigation",
                        "navigation", registry.GetNavigationHandle());
  GetContentClient()->browser()->CreateThrottlesForNavigation(registry);
}

std::vector<std::unique_ptr<CommitDeferringCondition>>
WebContentsImpl::CreateDeferringConditionsForNavigationCommit(
    NavigationHandle& navigation_handle,
    CommitDeferringCondition::NavigationType type) {
  OPTIONAL_TRACE_EVENT2(
      "content", "WebContentsImpl::CreateDeferringConditionsForNavigation",
      "navigation", navigation_handle, "NavigationType", type);
  std::vector<std::unique_ptr<CommitDeferringCondition>> conditions =
      GetContentClient()
          ->browser()
          ->CreateCommitDeferringConditionsForNavigation(&navigation_handle,
                                                         type);

  if (auto condition = JavaScriptDialogCommitDeferringCondition::MaybeCreate(
          static_cast<NavigationRequest&>(navigation_handle))) {
    conditions.push_back(std::move(condition));
  }
  return conditions;
}

std::unique_ptr<NavigationUIData> WebContentsImpl::GetNavigationUIData(
    NavigationHandle* navigation_handle) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::GetNavigationUIData");
  return GetContentClient()->browser()->GetNavigationUIData(navigation_handle);
}

void WebContentsImpl::RegisterExistingOriginAsHavingDefaultIsolation(
    const url::Origin& origin,
    NavigationRequest* navigation_request_to_exclude) {
  OPTIONAL_TRACE_EVENT2(
      "content",
      "WebContentsImpl::RegisterExistingOriginAsHavingDefaultIsolation",
      "origin", origin, "navigation_request_to_exclude",
      navigation_request_to_exclude);
  // Note: This function can be made static if we ever need call it without
  // a WebContentsImpl instance, in which case we can use a wrapper to
  // implement the override from NavigatorDelegate.
  for (WebContentsImpl* web_contents : GetAllWebContents()) {
    // We only need to search entries in the same BrowserContext as us.
    if (web_contents->GetBrowserContext() != GetBrowserContext()) {
      continue;
    }

    // Walk the frame trees to notify each one's NavigationController about the
    // opting-in or opting-out `origin`, and also pick up any frames without
    // FrameNavigationEntries.
    // * Some frames won't have FrameNavigationEntries (Issues 524208, 608402).
    // * Some pending navigations won't have NavigationEntries.
    web_contents->ForEachFrameTree(
        [origin, navigation_request_to_exclude](FrameTree& frame_tree) {
          frame_tree.RegisterExistingOriginAsHavingDefaultIsolation(
              origin, navigation_request_to_exclude);
        });
  }
}

bool WebContentsImpl::MaybeCopyContentAreaAsBitmap(
    base::OnceCallback<void(const SkBitmap&)> callback) {
  if (!GetDelegate()) {
    return false;
  }
  return GetDelegate()->MaybeCopyContentAreaAsBitmap(std::move(callback));
}

bool WebContentsImpl::SupportsForwardTransitionAnimation() {
#if BUILDFLAG(IS_ANDROID)
  return supports_forward_transition_animation_;
#else
  return true;
#endif  // !BUILDFLAG(IS_ANDROID)
}

#if BUILDFLAG(IS_ANDROID)
void WebContentsImpl::SetSupportsForwardTransitionAnimation(bool supports) {
  supports_forward_transition_animation_ = supports;
}
#endif  // !BUILDFLAG(IS_ANDROID)

void WebContentsImpl::DidChangeName(RenderFrameHostImpl* render_frame_host,
                                    const std::string& name) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::DidChangeName",
                        "render_frame_host", render_frame_host, "name", name);
  observers_.NotifyObservers(&WebContentsObserver::FrameNameChanged,
                             render_frame_host, name);
}

void WebContentsImpl::DidReceiveUserActivation(
    RenderFrameHostImpl* render_frame_host) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::DidReceiveUserActivation",
                        "render_frame_host", render_frame_host);
  observers_.NotifyObservers(&WebContentsObserver::FrameReceivedUserActivation,
                             render_frame_host);
}

void WebContentsImpl::WebAuthnAssertionRequestSucceeded(
    RenderFrameHostImpl* render_frame_host) {
  OPTIONAL_TRACE_EVENT1("content",
                        "WebContentsImpl::WebAuthnAssertionRequestSucceeded",
                        "render_frame_host", render_frame_host);
  observers_.NotifyObservers(
      &WebContentsObserver::WebAuthnAssertionRequestSucceeded,
      render_frame_host);
}

void WebContentsImpl::BindDisplayCutoutHost(
    RenderFrameHostImpl* render_frame_host,
    mojo::PendingAssociatedReceiver<blink::mojom::DisplayCutoutHost> receiver) {
  if (safe_area_insets_host_) {
    safe_area_insets_host_->BindReceiver(std::move(receiver),
                                         render_frame_host);
  }
}

void WebContentsImpl::DidChangeDisplayState(
    RenderFrameHostImpl* render_frame_host,
    bool is_display_none) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::DidChangeDisplayState",
                        "render_frame_host", render_frame_host,
                        "is_display_none", is_display_none);
  observers_.NotifyObservers(&WebContentsObserver::FrameDisplayStateChanged,
                             render_frame_host, is_display_none);
}

void WebContentsImpl::FrameSizeChanged(RenderFrameHostImpl* render_frame_host,
                                       const gfx::Size& frame_size) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::FrameSizeChanged",
                        "render_frame_host", render_frame_host);
  observers_.NotifyObservers(&WebContentsObserver::FrameSizeChanged,
                             render_frame_host, frame_size);
}

void WebContentsImpl::DocumentOnLoadCompleted(
    RenderFrameHostImpl* render_frame_host) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::DocumentOnLoadCompleted",
                        "render_frame_host", render_frame_host);
  DCHECK(render_frame_host->is_main_frame());
  if (!render_frame_host->IsOutermostMainFrame()) {
    // If this main frame isn't an outermost main frame but an embedded
    // main frame then return. )ie. a fenced frame inside a guest).
    return;
  }

  if (auto* guest =
          GuestPageHolderImpl::FromRenderFrameHost(*render_frame_host)) {
    ShowInsecureLocalhostWarningIfNeeded(render_frame_host->GetPage());
    guest->delegate()->GuestDocumentOnLoadCompleted();
  } else if (render_frame_host->IsInPrimaryMainFrame()) {
    // Don't dispatch DocumentOnLoadCompletedInPrimaryMainFrame for non-primary
    // main frames. As most of the observers are interested only in the onload
    // completion of the current document in the primary main frame. Since the
    // WebContents could be hosting more than one main frame (e.g., fenced
    // frames, prerender pages or pending delete RFHs), return early for other
    // cases. In case of prerendering, we dispatch
    // DocumentOnLoadCompletedInPrimaryMainFrame on activation.
    ShowInsecureLocalhostWarningIfNeeded(render_frame_host->GetPage());
    observers_.NotifyObservers(
        &WebContentsObserver::DocumentOnLoadCompletedInPrimaryMainFrame);
  }
}

void WebContentsImpl::UpdateTitle(RenderFrameHostImpl* render_frame_host,
                                  const std::u16string& title,
                                  base::i18n::TextDirection title_direction) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::UpdateTitle",
                        "render_frame_host", render_frame_host, "title", title);
  // Try to find the navigation entry, which might not be the current one.
  // For example, it might be from a pending deletion RFH, or it might be from a
  // non-primary frame tree.
  NavigationEntryImpl* entry =
      render_frame_host->frame_tree()->controller().GetEntryWithUniqueID(
          render_frame_host->nav_entry_id());

  if (!entry) {
    // We can handle title updates with no matching NavigationEntry, but only if
    // the update is for the initial NavigationEntry. In that case the initial
    // empty document RFH wouldn't have a `nav_entry_id` set because it hasn't
    // committed any navigation. Note that if the title update came from the
    // initial empty document but the WebContents is doing a session restore,
    // we will ignore the title update (because GetLastCommittedEntry() would
    // return the non-initial restored entry), which avoids accidental
    // overwriting of the restored entry's title.
    if (render_frame_host->GetParent() || !render_frame_host->frame_tree()
                                               ->controller()
                                               .GetLastCommittedEntry()
                                               ->IsInitialEntry()) {
      return;
    }
    entry =
        render_frame_host->frame_tree()->controller().GetLastCommittedEntry();
  }

  // TODO(evan): make use of title_direction.
  // http://code.google.com/p/chromium/issues/detail?id=27094
  bool title_changed = UpdateTitleForEntryImpl(entry, title);
  if (title_changed) {
    if (render_frame_host == GetPrimaryMainFrame()) {
      NotifyTitleUpdateForEntry(entry);
    }
    SCOPED_UMA_HISTOGRAM_TIMER("WebContentsObserver.TitleWasSetForMainFrame");
    observers_.NotifyObservers(&WebContentsObserver::TitleWasSetForMainFrame,
                               render_frame_host);
  }
}

void WebContentsImpl::UpdateApplicationTitle(
    RenderFrameHostImpl* render_frame_host,
    const std::u16string& application_title) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::UpdateTitle",
                        "render_frame_host", render_frame_host,
                        "application_title", application_title);
  // Same logic as UpdateTitle() above.
  NavigationEntryImpl* entry =
      render_frame_host->frame_tree()->controller().GetEntryWithUniqueID(
          render_frame_host->nav_entry_id());
  if (!entry) {
    if (render_frame_host->GetParent() || !render_frame_host->frame_tree()
                                               ->controller()
                                               .GetLastCommittedEntry()
                                               ->IsInitialEntry()) {
      return;
    }
    entry =
        render_frame_host->frame_tree()->controller().GetLastCommittedEntry();
  }
  std::u16string final_application_title;
  base::TrimWhitespace(application_title, base::TRIM_ALL,
                       &final_application_title);

  if (final_application_title == entry->GetApplicationTitle()) {
    return;
  }

  entry->SetApplicationTitle(final_application_title);
  NotifyNavigationStateChanged(INVALIDATE_TYPE_TITLE);
}

void WebContentsImpl::UpdateTargetURL(RenderFrameHostImpl* render_frame_host,
                                      const GURL& url) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::UpdateTargetURL",
                        "render_frame_host", render_frame_host, "url", url);
  // In case of racey updates from multiple RenderViewHosts, the last URL should
  // be shown - see also some discussion in https://crbug.com/807776.
  if (!url.is_valid() && render_frame_host != frame_that_set_last_target_url_) {
    return;
  }
  frame_that_set_last_target_url_ =
      url.is_valid() ? render_frame_host : nullptr;

  if (delegate_) {
    delegate_->UpdateTargetURL(this, url);
  }
}

void WebContentsImpl::SetAsFocusedWebContentsIfNecessary() {
  SetFocusedFrameTree(&GetPrimaryFrameTree());
}

void WebContentsImpl::SetFocusedFrameTree(FrameTree* frame_tree_to_focus) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::SetFocusedFrameTree");
  DCHECK(frame_tree_to_focus);

  // Only change focus if we are not currently focused.
  FrameTree* old_focused_frame_tree = GetFocusedFrameTree();
  if (old_focused_frame_tree == frame_tree_to_focus) {
    return;
  }

  GetOutermostWebContents()->node_.SetFocusedFrameTree(frame_tree_to_focus);

  // Send a page level blur to the `old_focused_frame_tree` so that it displays
  // inactive UI and focus `frame_tree_to_focus` to activate it.
  if (old_focused_frame_tree) {
    old_focused_frame_tree->root()
        ->current_frame_host()
        ->GetRenderWidgetHost()
        ->SetPageFocus(false);
  }

  // Make sure the outer frame trees knows our frame is focused. Otherwise, the
  // outer renderer could have the element before or after the frame element
  // focused which would return early without actually advancing focus.
  RenderFrameHostImpl::UpdateAXFocusDeferScope focus_defer_scope(
      *frame_tree_to_focus->root()
           ->current_frame_host()
           ->GetOutermostMainFrameOrEmbedder());
  if (frame_tree_to_focus->GetFocusedFrame() &&
      frame_tree_to_focus->GetFocusedFrame()
          ->current_frame_host()
          ->inner_tree_main_frame_tree_node_id()) {
    // If an inner frame tree, in `frame_tree_to_focus`, had focus, the
    // placeholder RenderFrameHost needs to be unset as the focused frame in
    // `frame_tree_to_focus`.
    frame_tree_to_focus->SetFocusedFrame(frame_tree_to_focus->root(), nullptr);
  }
  frame_tree_to_focus->FocusOuterFrameTrees();

  frame_tree_to_focus->root()
      ->current_frame_host()
      ->GetRenderWidgetHost()
      ->SetPageFocus(true);
}

void WebContentsImpl::SetFocusedFrame(FrameTreeNode* node,
                                      SiteInstanceGroup* source) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::SetFocusedFrame",
                        "frame_tree_node", node, "source_site_instance_group",
                        source);

  if (GetFocusedFrameTree()->GetFocusedFrame()) {
    RenderFrameHostImpl* focused_rfh =
        GetFocusedFrameTree()->GetFocusedFrame()->current_frame_host();
    // This is only enforced for focus changes that cross a fenced frame
    // boundary.
    if (!node->current_frame_host()->VerifyFencedFrameFocusChange(
            focused_rfh)) {
      return;
    }
  }

  // Focus will not be in a consistent state until the focused frame tree is
  // also updated (if necessary).
  RenderFrameHostImpl::UpdateAXFocusDeferScope focus_defer_scope(
      *node->current_frame_host()->GetOutermostMainFrameOrEmbedder());

  node->frame_tree().SetFocusedFrame(node, source);

  auto* inner_contents = node_.GetInnerWebContentsInFrame(node);

  // We currently do not need to descend into inner frame trees that
  // are not an inner WebContents for focus. If `inner_contents` is null,
  // then the only supported inner frame tree type would be fenced frames.
  // An embedding frame focusing a fenced frame is not allowed since that would
  // be an information leak.  If a renderer attempts to do that, that should be
  // blocked by `RenderFrameProxyHost::DidFocusFrame()`.
  //
  // TODO(https://crbug.com/376085320): MPArch based <webview> allows focus on
  // the inner frame tree node. For now, disable this DCHECK when the flag is
  // enabled.
  DCHECK(base::FeatureList::IsEnabled(features::kGuestViewMPArch) ||
         inner_contents ||
         node->current_frame_host()
             ->inner_tree_main_frame_tree_node_id()
             .is_null());

  if (inner_contents) {
    // An inner WebContents is not created from Fenced Frames so we
    // shouldn't end up in this branch.
    DCHECK(!node->IsInFencedFrameTree());

    // |this| is an outer WebContents and |node| represents an inner
    // WebContents. Transfer the focus to the inner contents if |this| is
    // focused.
    if (GetFocusedWebContents() == this) {
      inner_contents->SetAsFocusedWebContentsIfNecessary();
    }
  } else if (node_.OuterContentsFrameTreeNode() &&
             node_.OuterContentsFrameTreeNode()
                     ->current_frame_host()
                     ->GetSiteInstance()
                     ->group() == source) {
    // A GuestView embedding a fenced frame will have an
    // OuterContentsFrameTreeNode. However, it will not have the same site
    // instance because a FencedFrame creates a new BrowsingInstance.
    DCHECK(!node->IsInFencedFrameTree());

    // |this| is an inner WebContents, |node| is its main FrameTreeNode and
    // the outer WebContents FrameTreeNode is at |source|'s SiteInstance.
    // Transfer the focus to the inner WebContents if the outer WebContents is
    // focused. This branch is used when an inner WebContents is focused through
    // its RenderFrameProxyHost (via FrameFocused mojo call, used to
    // implement the window.focus() API).
    if (GetFocusedWebContents() == GetOuterWebContents()) {
      SetFocusedFrameTree(&node->frame_tree());
    }
  } else if (!GetOuterWebContents() || GetFocusedWebContents() == this) {
    // This is an outermost WebContents or we are currently focused so allow
    // the requested node's frame tree to be focused. The
    // (GetFocusedWebContents() == this) is needed when there are multiple
    // frame trees within an inner WebContents (ie. a GuestView with fenced
    // frames).
    SetFocusedFrameTree(&node->frame_tree());
  }

  CloseListenerManager::DidChangeFocusedFrame(this);
}

FrameTree* WebContentsImpl::GetOwnedPictureInPictureFrameTree() {
#if !BUILDFLAG(IS_ANDROID)
  if (has_picture_in_picture_document_) {
    WebContents* picture_in_picture_web_contents =
        PictureInPictureWindowController::
            GetOrCreateDocumentPictureInPictureController(this)
                ->GetChildWebContents();
    if (picture_in_picture_web_contents) {
      return &(static_cast<WebContentsImpl*>(picture_in_picture_web_contents)
                   ->GetPrimaryFrameTree());
    }
  }
#endif  // !BUILDFLAG(IS_ANDROID)

  return nullptr;
}

FrameTree* WebContentsImpl::GetPictureInPictureOpenerFrameTree() {
#if !BUILDFLAG(IS_ANDROID)
  if (picture_in_picture_opener_) {
    return &(static_cast<WebContentsImpl*>(picture_in_picture_opener_.get())
                 ->GetPrimaryFrameTree());
  }
#endif  // !BUILDFLAG(IS_ANDROID)

  return nullptr;
}

void WebContentsImpl::DidCallFocus() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::DidCallFocus");
  // Any explicit focusing of another window while this WebContents is in
  // fullscreen can be used to confuse the user, so drop fullscreen.
  base::ScopedClosureRunner fullscreen_block =
      ForSecurityDropFullscreen(/*display_id=*/display::kInvalidDisplayId);
  // The other contents is independent of this contents, so release the
  // fullscreen block.
  fullscreen_block.RunAndReset();
}

void WebContentsImpl::OnAdvanceFocus(RenderFrameHostImpl* source_rfh) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::OnAdvanceFocus",
                        "render_frame_host", source_rfh);
  // When a RenderFrame needs to advance focus to a `blink::RemoteFrame` (by
  // hitting TAB), the `blink::RemoteFrame` sends an IPC to
  // RenderFrameProxyHost. When this RenderFrameProxyHost represents an inner
  // WebContents, the outer WebContents needs to focus the inner WebContents.
  if (GetOuterWebContents() &&
      GetOuterWebContents() == WebContents::FromRenderFrameHost(source_rfh) &&
      GetFocusedWebContents() == GetOuterWebContents()) {
    SetAsFocusedWebContentsIfNecessary();
  }
}

void WebContentsImpl::OnFocusedElementChangedInFrame(
    RenderFrameHostImpl* frame,
    const gfx::Rect& bounds_in_root_view,
    blink::mojom::FocusType focus_type) {
  OPTIONAL_TRACE_EVENT1("content",
                        "WebContentsImpl::OnFocusedElementChangedInFrame",
                        "render_frame_host", frame);
  RenderWidgetHostViewBase* root_view =
      static_cast<RenderWidgetHostViewBase*>(GetRenderWidgetHostView());
  if (!root_view || !frame->GetView()) {
    return;
  }
  // Convert to screen coordinates from window coordinates by adding the
  // window's origin.
  gfx::Point origin = bounds_in_root_view.origin();
  origin += root_view->GetViewBounds().OffsetFromOrigin();
  gfx::Rect bounds_in_screen(origin, bounds_in_root_view.size());

  root_view->FocusedNodeChanged(frame->has_focused_editable_element(),
                                bounds_in_screen);

  FocusedNodeDetails details = {frame->has_focused_editable_element(),
                                bounds_in_screen, bounds_in_root_view,
                                focus_type};
  BrowserAccessibilityStateImpl::GetInstance()->OnFocusChangedInPage(details);
  observers_.NotifyObservers(&WebContentsObserver::OnFocusChangedInPage,
                             details);
}

bool WebContentsImpl::DidAddMessageToConsole(
    RenderFrameHostImpl* source_frame,
    blink::mojom::ConsoleMessageLevel log_level,
    const std::u16string& message,
    int32_t line_no,
    const std::u16string& source_id,
    const std::optional<std::u16string>& untrusted_stack_trace) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::DidAddMessageToConsole",
                        "message", message);

  observers_.NotifyObservers(&WebContentsObserver::OnDidAddMessageToConsole,
                             source_frame, log_level, message, line_no,
                             source_id, untrusted_stack_trace);

  if (!delegate_) {
    return false;
  }
  return delegate_->DidAddMessageToConsole(this, log_level, message, line_no,
                                           source_id);
}

void WebContentsImpl::DidReceiveInputEvent(
    RenderWidgetHostImpl* render_widget_host,
    const blink::WebInputEvent& event) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::DidReceiveInputEvent",
                        "render_widget_host", render_widget_host);

  if (event.GetType() == blink::WebInputEvent::Type::kMouseDown &&
      static_cast<const blink::WebMouseEvent&>(event).button ==
          blink::WebPointerProperties::Button::kBack) {
    BackNavigationLikely(content_preloading_predictor::kMouseBackButton,
                         WindowOpenDisposition::CURRENT_TAB);
  }

  if (!IsUserInteractionInputType(event.GetType())) {
    return;
  }

  // Ignore unless the widget is currently in the frame tree.
  if (!HasMatchingWidgetHost(&primary_frame_tree_, render_widget_host)) {
    return;
  }

  if (event.GetType() != blink::WebInputEvent::Type::kGestureScrollBegin) {
    last_interaction_time_ = ui::EventTimeForNow();
  }

  observers_.NotifyObservers(&WebContentsObserver::DidGetUserInteraction,
                             event);
}

bool WebContentsImpl::ShouldIgnoreWebInputEvents(
    const blink::WebInputEvent& event) {
  if (ignore_input_events_count_ > 0) {
    return true;
  }
  for (const auto& callback : web_input_event_audit_callbacks_) {
    if (!callback.second.Run(event)) {
      return true;
    }
  }
  WebContentsImpl* web_contents = GetOuterWebContents();
  if (!web_contents) {
    return false;
  }
  return web_contents->ShouldIgnoreWebInputEvents(event);
}

bool WebContentsImpl::ShouldIgnoreInputEvents() {
  if (ignore_input_events_count_ > 0 ||
      !web_input_event_audit_callbacks_.empty()) {
    return true;
  }
  WebContentsImpl* web_contents = GetOuterWebContents();
  if (!web_contents) {
    return false;
  }
  return web_contents->ShouldIgnoreInputEvents();
}

bool WebContentsImpl::ShouldIgnoreA11yInputEvents() {
  if (ignore_a11y_input_count_ > 0) {
    return true;
  }
  WebContentsImpl* web_contents = GetOuterWebContents();
  if (!web_contents) {
    return false;
  }
  return web_contents->ShouldIgnoreA11yInputEvents();
}

void WebContentsImpl::FocusOwningWebContents(
    RenderWidgetHostImpl* render_widget_host) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::FocusOwningWebContents",
                        "render_widget_host", render_widget_host);
  RenderWidgetHostImpl* main_frame_widget_host =
      GetPrimaryMainFrame()->GetRenderWidgetHost();
  RenderWidgetHostImpl* focused_widget =
      GetFocusedRenderWidgetHost(main_frame_widget_host);

  if (focused_widget != render_widget_host &&
      (!focused_widget ||
       focused_widget->delegate() != render_widget_host->delegate())) {
#if BUILDFLAG(IS_ANDROID)
    if (&GetPrimaryFrameTree() != GetFocusedFrameTree()) {
      UMA_HISTOGRAM_BOOLEAN("Android.FocusChanged.FocusOwningWebContents",
                            true);
    }
#endif
    SetAsFocusedWebContentsIfNecessary();
  } else {
#if BUILDFLAG(IS_ANDROID)
    UMA_HISTOGRAM_BOOLEAN("Android.FocusChanged.FocusOwningWebContents", false);
#endif
  }
}

void WebContentsImpl::OnIgnoredUIEvent() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::OnIgnoredUIEvent");
  // Notify observers.
  observers_.NotifyObservers(&WebContentsObserver::DidGetIgnoredUIEvent);
}

void WebContentsImpl::RendererUnresponsive(
    RenderWidgetHostImpl* render_widget_host,
    base::RepeatingClosure hang_monitor_restarter) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::RendererUnresponsive",
                        "render_widget_host", render_widget_host);
  if (ShouldIgnoreUnresponsiveRenderer()) {
    return;
  }

  bool visible = GetVisibility() == Visibility::VISIBLE;
  RecordRendererUnresponsiveMetrics(visible, render_widget_host);

  // Do not report hangs (to task manager, to hang renderer dialog, etc.) for
  // invisible tabs (like extension background page, background tabs).  See
  // https://crbug.com/881812 for rationale and for choosing the visibility
  // (rather than process priority) as the signal here.
  if (!visible) {
    return;
  }

  if (!render_widget_host->renderer_initialized()) {
    return;
  }

  CrashRepHandlingOutcome outcome =
      base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kNoErrorDialogs)
          ? CrashRepHandlingOutcome::kDropped
          : CrashRepHandlingOutcome::kPotentiallyQueued;
  base::UmaHistogramEnumeration(
      "ReportingAndNEL.UnresponsiveRenderer.CrashReportOutcome", outcome);

  if (base::FeatureList::IsEnabled(
          blink::features::kDocumentPolicyIncludeJSCallStacksInCrashReports) &&
      this->GetLastCommittedURL().SchemeIsHTTPOrHTTPS()) {
    RenderProcessHost* rph = render_widget_host->GetProcess();
    if (rph) {
      RenderProcessHostImpl* process_host =
          static_cast<RenderProcessHostImpl*>(rph);
      process_host->InterruptJavaScriptIsolateAndCollectCallStack();
    }
  }

  observers_.NotifyObservers(&WebContentsObserver::OnRendererUnresponsive,
                             render_widget_host->GetProcess());
  if (delegate_) {
    delegate_->RendererUnresponsive(this, render_widget_host,
                                    std::move(hang_monitor_restarter));
  }
}

void WebContentsImpl::RendererResponsive(
    RenderWidgetHostImpl* render_widget_host) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::RenderResponsive",
                        "render_widget_host", render_widget_host);
  observers_.NotifyObservers(&WebContentsObserver::OnRendererResponsive,
                             render_widget_host->GetProcess());

  if (delegate_) {
    delegate_->RendererResponsive(this, render_widget_host);
  }
}

void WebContentsImpl::BeforeUnloadFiredFromRenderManager(
    bool proceed,
    bool* proceed_to_fire_unload) {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::BeforeUnloadFiredFromRenderManager");
  observers_.NotifyObservers(&WebContentsObserver::BeforeUnloadFired, proceed);
  if (delegate_) {
    delegate_->BeforeUnloadFired(this, proceed, proceed_to_fire_unload);
  }
  // Note: |this| might be deleted at this point.
}

void WebContentsImpl::CancelDialogManagerDialogs(bool reset_state) {
  if (!created_dialog_since_last_cancel_) {
    return;
  }
  // We only reset `created_dialog_since_last_cancel_` if reset_state
  // is true.
  if (reset_state) {
    created_dialog_since_last_cancel_ = false;
  }
  if (!delegate_) {
    return;
  }
  JavaScriptDialogManager* dialog_manager =
      delegate_->GetJavaScriptDialogManager(this);
  if (!dialog_manager) {
    return;
  }
  dialog_manager->CancelDialogs(this, reset_state);
}

void WebContentsImpl::CancelModalDialogsForRenderManager() {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::CancelModalDialogsForRenderManager");
  // We need to cancel modal dialogs when doing a process swap, since the load
  // deferrer would prevent us from swapping out. We also clear the state
  // because this is a cross-process navigation, which means that it's a new
  // site that should not have to pay for the sins of its predecessor.
  //
  // Note that we don't bother telling |browser_plugin_embedder_| because the
  // cross-process navigation will either destroy the browser plugins or not
  // require their dialogs to close.
  CancelDialogManagerDialogs(/*reset_state=*/true);
}

void WebContentsImpl::NotifySwappedFromRenderManager(
    RenderFrameHostImpl* old_frame,
    RenderFrameHostImpl* new_frame) {
  TRACE_EVENT2("content", "WebContentsImpl::NotifySwappedFromRenderManager",
               "old_render_frame_host", old_frame, "new_render_frame_host",
               new_frame);
  DCHECK_NE(new_frame->lifecycle_state(),
            RenderFrameHostImpl::LifecycleStateImpl::kSpeculative);

  // Only fire RenderViewHostChanged if it is related to our FrameTree, as
  // observers can not deal with events coming from non-primary FrameTree.
  // TODO(crbug.com/40165060): Update observers to deal with the events,
  // and fire events for all frame trees.
  if (new_frame->IsInPrimaryMainFrame()) {
    // The |new_frame| and its various compadres are already swapped into place
    // for the WebContentsImpl when this method is called.
    DCHECK_EQ(
        primary_frame_tree_.root()->render_manager()->GetRenderWidgetHostView(),
        new_frame->GetView());

    RenderViewHost* old_rvh =
        old_frame ? old_frame->GetRenderViewHost() : nullptr;
    RenderViewHost* new_rvh = new_frame->GetRenderViewHost();
    // |old_rvh| and |new_rvh| might be equal when navigating from a crashed
    // RenderFrameHost to a new same-site one. With RenderDocument, this will
    // happen for every same-site navigation.
    if (old_rvh != new_rvh) {
      NotifyViewSwapped(old_rvh, new_rvh);
    }

    auto* rwhv = static_cast<RenderWidgetHostViewBase*>(new_frame->GetView());
    if (rwhv) {
      rwhv->SetMainFrameAXTreeID(new_frame->GetAXTreeID());

      // The RenderWidgetHostView for the speculative RenderFrameHost is not
      // resized with the current RenderFrameHost while a navigation is
      // pending. So when we swap in the main frame, we need to update the
      // RenderWidgetHostView's size.
      //
      // Historically, this was done to fix b/1079768 for interstitials.
      rwhv->SetSize(GetSizeForMainFrame());
    }

    NotifyPrimaryMainFrameProcessIsAlive();
  }

  NotifyFrameSwapped(old_frame, new_frame);
}

void WebContentsImpl::NotifySwappedFromRenderManagerWithoutFallbackContent(
    RenderFrameHostImpl* new_frame) {
  auto* rwhv = static_cast<RenderWidgetHostViewBase*>(new_frame->GetView());
  if (rwhv) {
    rwhv->ClearFallbackSurfaceForCommitPending();
  }
}

void WebContentsImpl::NotifyMainFrameSwappedFromRenderManager(
    RenderFrameHostImpl* old_frame,
    RenderFrameHostImpl* new_frame) {
  // Only fire RenderViewHostChanged if it is
  // related to our FrameTree, as observers cannot deal with events coming
  // from non-primary FrameTree.
  // TODO(crbug.com/40165060): Update observers to deal with the events,
  // and fire events for all frame trees.
  if (!new_frame->IsInPrimaryMainFrame()) {
    return;
  }
  NotifyViewSwapped(old_frame ? old_frame->GetRenderViewHost() : nullptr,
                    new_frame->GetRenderViewHost());
}

void WebContentsImpl::CreateRenderWidgetHostViewForRenderManager(
    RenderViewHost* render_view_host) {
  OPTIONAL_TRACE_EVENT1(
      "content", "WebContentsImpl::CreateRenderWidgetHostViewForRenderManager",
      "render_view_host", render_view_host);

  bool is_inner_frame_tree = [&]() {
    FrameTree* frame_tree =
        static_cast<RenderViewHostImpl*>(render_view_host)->frame_tree();
    switch (frame_tree->type()) {
      case FrameTree::Type::kPrimary:
      case FrameTree::Type::kPrerender:
        return false;
      case FrameTree::Type::kFencedFrame:
      case FrameTree::Type::kGuest:
        return true;
    }
  }();

  if (is_inner_frame_tree) {
    WebContentsViewChildFrame::CreateRenderWidgetHostViewForInnerFrameTree(
        this, render_view_host->GetWidget());
  } else {
    RenderWidgetHostViewBase* rwh_view =
        view_->CreateViewForWidget(render_view_host->GetWidget());
    view_->SetOverscrollControllerEnabled(CanOverscrollContent());
    rwh_view->SetSize(GetSizeForMainFrame());
  }
}

void WebContentsImpl::ReattachOuterDelegateIfNeeded() {
  if (node_.outer_web_contents()) {
    ReattachToOuterWebContentsFrame();
  }
}

bool WebContentsImpl::CreateRenderViewForRenderManager(
    RenderViewHost* render_view_host,
    const std::optional<blink::FrameToken>& opener_frame_token,
    RenderFrameProxyHost* proxy_host,
    const std::optional<base::UnguessableToken>& navigation_metrics_token) {
  TRACE_EVENT1("browser,navigation",
               "WebContentsImpl::CreateRenderViewForRenderManager",
               "render_view_host", render_view_host);
  auto* rvh_impl = static_cast<RenderViewHostImpl*>(render_view_host);
  // Observers should not destroy the WebContents here or we will crash as the
  // stack unwinds. See crbug.com/1181043.
  base::AutoReset<bool> scope(&prevent_destruction_, true);

  if (!proxy_host) {
    CreateRenderWidgetHostViewForRenderManager(render_view_host);
  }

  const auto proxy_routing_id =
      proxy_host ? proxy_host->GetRoutingID() : IPC::mojom::kRoutingIdNone;
  // TODO(crbug.com/40166243): Given MPArch, should we pass
  // opened_by_another_window_ for non primary FrameTrees?
  if (!rvh_impl->CreateRenderView(opener_frame_token, proxy_routing_id,
                                  opened_by_another_window_,
                                  navigation_metrics_token)) {
    return false;
  }

  // Set the TextAutosizer state from the main frame's renderer on the new view,
  // but only if it's not for the main frame. Main frame renderers should create
  // this state themselves from up-to-date values, so we shouldn't override it
  // with the cached values.
  if (!rvh_impl->GetMainRenderFrameHost() && proxy_host) {
    proxy_host->GetAssociatedRemoteMainFrame()->UpdateTextAutosizerPageInfo(
        proxy_host->frame_tree_node()
            ->current_frame_host()
            ->GetPage()
            .text_autosizer_page_info()
            .Clone());
  }

  // If `render_view_host` is for an inner WebContents, ensure that its
  // RenderWidgetHostView is properly reattached to the outer WebContents. Note
  // that this should only be done when `render_view_host` is already the
  // current RenderViewHost in this WebContents.  If it isn't, the reattachment
  // will happen later when `render_view_host` becomes current as part of
  // committing the speculative RenderFrameHost it's associated with.
  if (!proxy_host && render_view_host == GetRenderViewHost()) {
    ReattachOuterDelegateIfNeeded();
  }

  // With SetHistoryInfoOnViewCreation enabled, the history and index length are
  // sent as part of the the CreateView() IPC via the CreateViewParams.
  if (!base::FeatureList::IsEnabled(features::kSetHistoryInfoOnViewCreation)) {
    SetHistoryIndexAndLengthForView(
        render_view_host,
        rvh_impl->frame_tree()->controller().GetLastCommittedEntryIndex(),
        rvh_impl->frame_tree()->controller().GetEntryCount());
  }

#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_ANDROID)
  // Force a ViewMsg_Resize to be sent, needed to make plugins show up on
  // linux. See crbug.com/83941.
  RenderWidgetHostView* rwh_view = render_view_host->GetWidget()->GetView();
  if (rwh_view) {
    if (RenderWidgetHost* render_widget_host =
            rwh_view->GetRenderWidgetHost()) {
      render_widget_host->SynchronizeVisualProperties();
    }
  }
#endif

  return true;
}

#if BUILDFLAG(IS_ANDROID)

base::android::ScopedJavaLocalRef<jobject>
WebContentsImpl::GetJavaWebContents() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  return GetWebContentsAndroid()->GetJavaObject();
}

base::android::ScopedJavaLocalRef<jthrowable>
WebContentsImpl::GetJavaCreatorLocation() {
  return base::android::ScopedJavaLocalRef<jthrowable>(java_creator_location_);
}

WebContentsAndroid* WebContentsImpl::GetWebContentsAndroid() {
  if (!web_contents_android_) {
    web_contents_android_ = std::make_unique<WebContentsAndroid>(this);
  }
  return web_contents_android_.get();
}

void WebContentsImpl::ClearWebContentsAndroid() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  web_contents_android_.reset();
}

void WebContentsImpl::ActivateNearestFindResult(float x, float y) {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::ActivateNearestFindResult");
  GetOrCreateFindRequestManager()->ActivateNearestFindResult(x, y);
}

void WebContentsImpl::RequestFindMatchRects(int current_version) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::RequestFindMatchRects");
  GetOrCreateFindRequestManager()->RequestFindMatchRects(current_version);
}

service_manager::InterfaceProvider* WebContentsImpl::GetJavaInterfaces() {
  if (!java_interfaces_) {
    mojo::PendingRemote<service_manager::mojom::InterfaceProvider> provider;
    BindInterfaceRegistryForWebContents(
        provider.InitWithNewPipeAndPassReceiver(), this);
    java_interfaces_ = std::make_unique<service_manager::InterfaceProvider>(
        base::SingleThreadTaskRunner::GetCurrentDefault());
    java_interfaces_->Bind(std::move(provider));
  }
  return java_interfaces_.get();
}

void WebContentsImpl::SetSelectionPopupDelegate(
    std::unique_ptr<SelectionPopupDelegate> delegate) {
  SelectionPopupController::FromWebContents(*this)->SetDelegate(
      std::move(delegate));
}

#endif

bool WebContentsImpl::CompletedFirstVisuallyNonEmptyPaint() {
  return GetPrimaryPage().did_first_visually_non_empty_paint();
}

void WebContentsImpl::OnDidDownloadImage(
    base::WeakPtr<RenderFrameHostImpl> rfh,
    ImageDownloadCallback callback,
    int id,
    const GURL& image_url,
    int32_t http_status_code,
    const std::vector<SkBitmap>& images,
    const std::vector<gfx::Size>& original_image_sizes) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::OnDidDownloadImage",
                        "image_url", image_url);

  // Guard against buggy or compromised renderers that could violate the API
  // contract that |images| and |original_image_sizes| must have the same
  // length.
  if (images.size() != original_image_sizes.size()) {
    if (rfh) {
      ReceivedBadMessage(rfh->GetProcess(),
                         bad_message::WCI_INVALID_DOWNLOAD_IMAGE_RESULT);
    }
    // Respond with a 400 to indicate that something went wrong.
    std::move(callback).Run(id, 400, image_url, std::vector<SkBitmap>(),
                            std::vector<gfx::Size>());
    return;
  }

  std::move(callback).Run(id, http_status_code, image_url, images,
                          original_image_sizes);
}

int WebContentsImpl::GetNextDownloadId() {
  static int next_image_download_id = 0;
  return ++next_image_download_id;
}

void WebContentsImpl::OnDialogClosed(int render_process_id,
                                     int render_frame_id,
                                     JavaScriptDialogCallback response_callback,
                                     base::ScopedClosureRunner fullscreen_block,
                                     bool dialog_was_suppressed,
                                     bool success,
                                     const std::u16string& user_input) {
  RenderFrameHostImpl* rfh =
      RenderFrameHostImpl::FromID(render_process_id, render_frame_id);
  // The user confirms and closes a dialog even after the page has navigated
  // away and got into BackForwardCache.
  DCHECK(!rfh || rfh->IsActive() || rfh->IsInBackForwardCache());
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::OnDialogClosed",
                        "render_frame_host", rfh);
  last_dialog_suppressed_ = dialog_was_suppressed;
  fullscreen_block.RunAndReset();

  javascript_dialog_dismiss_notifier_.reset();

  if (is_showing_before_unload_dialog_ && !success) {
    // It is possible for the current RenderFrameHost to have changed in the
    // meantime.  Do not reset the navigation state in that case.
    if (rfh && rfh == rfh->frame_tree_node()->current_frame_host()) {
      rfh->frame_tree_node()->BeforeUnloadCanceled();
      rfh->frame_tree()->controller().DiscardNonCommittedEntries();
    }

    // Update the URL display either way, to avoid showing a stale URL.
    NotifyNavigationStateChanged(INVALIDATE_TYPE_URL);

    observers_.NotifyObservers(
        &WebContentsObserver::BeforeUnloadDialogCancelled);
  }

  std::move(response_callback).Run(success, user_input);

  std::vector<protocol::PageHandler*> page_handlers =
      protocol::PageHandler::EnabledForWebContents(this);
  for (auto* handler : page_handlers) {
    handler->DidCloseJavaScriptDialog(rfh->devtools_frame_token(), success,
                                      user_input);
  }

  is_showing_javascript_dialog_ = false;
  is_showing_before_unload_dialog_ = false;
}

RenderFrameHostManager* WebContentsImpl::GetRenderManager() {
  return primary_frame_tree_.root()->render_manager();
}

BrowserPluginGuest* WebContentsImpl::GetBrowserPluginGuest() const {
  return browser_plugin_guest_.get();
}

void WebContentsImpl::SetBrowserPluginGuest(
    std::unique_ptr<BrowserPluginGuest> guest) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::SetBrowserPluginGuest");
  DCHECK(!browser_plugin_guest_);
  DCHECK(guest);
  browser_plugin_guest_ = std::move(guest);
}

base::UnguessableToken WebContentsImpl::GetAudioGroupId() {
  return GetAudioStreamFactory()->group_id();
}

const std::vector<blink::mojom::FaviconURLPtr>&
WebContentsImpl::GetFaviconURLs() {
  return GetPrimaryMainFrame()->FaviconURLs();
}

// The Mac and iOS implementations of the next two methods are in
// web_contents_impl_mac.mm and web_contents_impl_ios.mm.
#if !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_IOS)

void WebContentsImpl::Resize(const gfx::Rect& new_bounds) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::Resize");
#if defined(USE_AURA)
  aura::Window* window = GetNativeView();
  window->SetBounds(gfx::Rect(window->bounds().origin(), new_bounds.size()));
#elif BUILDFLAG(IS_ANDROID)
  content::RenderWidgetHostView* view = GetRenderWidgetHostView();
  if (view) {
    view->SetBounds(new_bounds);
  }
#endif
}

gfx::Size WebContentsImpl::GetSize() {
#if defined(USE_AURA)
  aura::Window* window = GetNativeView();
  return window->bounds().size();
#elif BUILDFLAG(IS_ANDROID)
  ui::ViewAndroid* view_android = GetNativeView();
  return view_android->GetSizeDIPs();
#endif
}

#endif  // !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_IOS)

gfx::Rect WebContentsImpl::GetWindowsControlsOverlayRect() const {
  return window_controls_overlay_rect_;
}

void WebContentsImpl::UpdateWindowControlsOverlay(
    const gfx::Rect& bounding_rect) {
  if (window_controls_overlay_rect_ == bounding_rect) {
    return;
  }

  window_controls_overlay_rect_ = bounding_rect;

  // Updates to the |window_controls_overlay_rect_| are sent via
  // the VisualProperties message.
  if (RenderWidgetHost* render_widget_host =
          GetPrimaryMainFrame()->GetRenderWidgetHost()) {
    render_widget_host->SynchronizeVisualProperties();
  }
}

BrowserPluginEmbedder* WebContentsImpl::GetBrowserPluginEmbedder() const {
  return browser_plugin_embedder_.get();
}

void WebContentsImpl::CreateBrowserPluginEmbedderIfNecessary() {
  OPTIONAL_TRACE_EVENT0(
      "content", "WebContentsImpl::CreateBrowserPluginEmbedderIfNecessary");
  if (browser_plugin_embedder_) {
    return;
  }
  browser_plugin_embedder_.reset(BrowserPluginEmbedder::Create(this));
}

gfx::Size WebContentsImpl::GetSizeForMainFrame() {
  if (delegate_) {
    // The delegate has a chance to specify a size independent of the UI.
    gfx::Size delegate_size = delegate_->GetSizeForNewRenderView(this);
    if (!delegate_size.IsEmpty()) {
      return delegate_size;
    }
  }

  // Device emulation, when enabled, can specify a size independent of the UI.
  if (!device_emulation_size_.IsEmpty()) {
    return device_emulation_size_;
  }

  return GetContainerBounds().size();
}

void WebContentsImpl::OnFrameTreeNodeDestroyed(FrameTreeNode* node) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::OnFrameTreeNodeDestroyed",
                        "node", node);
  // If we are the focused frame tree and are destroying the root node
  // reassign the focused frame tree node.
  if (!node->parent() && GetFocusedFrameTree() == &node->frame_tree() &&
      &node->frame_tree() != &primary_frame_tree_) {
    FrameTreeNode* frame_in_embedder =
        node->render_manager()->GetOuterDelegateNode();
    SetFocusedFrameTree(frame_in_embedder ? &frame_in_embedder->frame_tree()
                                          : &primary_frame_tree_);
  }

  observers_.NotifyObservers(&WebContentsObserver::FrameDeleted,
                             node->frame_tree_node_id());
}

void WebContentsImpl::OnPreferredSizeChanged(const gfx::Size& old_size) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::OnPreferredSizeChanged");
  if (!delegate_) {
    return;
  }
  const gfx::Size new_size = GetPreferredSize();
  if (new_size != old_size) {
    delegate_->UpdatePreferredSize(this, new_size);
  }
}

FindRequestManager* WebContentsImpl::GetFindRequestManager() {
  for (auto* contents = this; contents;
       contents = contents->GetOuterWebContents()) {
    if (contents->find_request_manager_) {
      return contents->find_request_manager_.get();
    }
  }

  return nullptr;
}

FindRequestManager* WebContentsImpl::GetOrCreateFindRequestManager() {
  if (FindRequestManager* manager = GetFindRequestManager()) {
    return manager;
  }

  DCHECK(!browser_plugin_guest_ || GetOuterWebContents());

  // No existing FindRequestManager found, so one must be created.
  find_request_manager_ = std::make_unique<FindRequestManager>(this);

  // Concurrent find sessions must not overlap, so destroy any existing
  // FindRequestManagers in any inner WebContentses.
  for (WebContents* contents : GetWebContentsAndAllInner()) {
    auto* web_contents_impl = static_cast<WebContentsImpl*>(contents);
    if (web_contents_impl == this) {
      continue;
    }
    if (web_contents_impl->find_request_manager_) {
      web_contents_impl->find_request_manager_->StopFinding(
          STOP_FIND_ACTION_CLEAR_SELECTION);
      web_contents_impl->find_request_manager_.release();
    }
  }

  return find_request_manager_.get();
}

void WebContentsImpl::NotifyFindReply(int request_id,
                                      int number_of_matches,
                                      const gfx::Rect& selection_rect,
                                      int active_match_ordinal,
                                      bool final_update) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::NotifyFindReply");
  if (delegate_ && !IsBeingDestroyed() &&
      !GetPrimaryMainFrame()->GetProcess()->FastShutdownStarted()) {
    delegate_->FindReply(this, request_id, number_of_matches, selection_rect,
                         active_match_ordinal, final_update);
  }
}

void WebContentsImpl::IncrementBluetoothConnectedDeviceCount() {
  OPTIONAL_TRACE_EVENT0(
      "content", "WebContentsImpl::IncrementBluetoothConnectedDeviceCount");
  // Trying to invalidate the tab state while being destroyed could result in a
  // use after free.
  if (IsBeingDestroyed()) {
    return;
  }
  // Notify for UI updates if the state changes.
  bluetooth_connected_device_count_++;
  if (bluetooth_connected_device_count_ == 1) {
    OnCapabilityTypesChanged(WebContentsCapabilityType::kBluetoothConnected,
                             /*used=*/true);
  }
}

void WebContentsImpl::DecrementBluetoothConnectedDeviceCount() {
  OPTIONAL_TRACE_EVENT0(
      "content", "WebContentsImpl::DecrementBluetoothConnectedDeviceCount");
  // Trying to invalidate the tab state while being destroyed could result in a
  // use after free.
  if (IsBeingDestroyed()) {
    return;
  }
  // Notify for UI updates if the state changes.
  DCHECK_NE(bluetooth_connected_device_count_, 0u);
  bluetooth_connected_device_count_--;
  if (bluetooth_connected_device_count_ == 0) {
    OnCapabilityTypesChanged(WebContentsCapabilityType::kBluetoothConnected,
                             /*used=*/false);
  }
}

void WebContentsImpl::IncrementBluetoothScanningSessionsCount() {
  OPTIONAL_TRACE_EVENT0(
      "content", "WebContentsImpl::IncrementBluetoothScanningSessionsCount");
  // Trying to invalidate the tab state while being destroyed could result in a
  // use after free.
  if (IsBeingDestroyed()) {
    return;
  }

  // Notify for UI updates if the state changes.
  bluetooth_scanning_sessions_count_++;
  if (bluetooth_scanning_sessions_count_ == 1) {
    NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
  }
}

void WebContentsImpl::DecrementBluetoothScanningSessionsCount() {
  OPTIONAL_TRACE_EVENT0(
      "content", "WebContentsImpl::DecrementBluetoothScanningSessionsCount");
  // Trying to invalidate the tab state while being destroyed could result in a
  // use after free.
  if (IsBeingDestroyed()) {
    return;
  }

  DCHECK_NE(0u, bluetooth_scanning_sessions_count_);
  bluetooth_scanning_sessions_count_--;
  if (bluetooth_scanning_sessions_count_ == 0) {
    NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
  }
}

void WebContentsImpl::IncrementSerialActiveFrameCount() {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::IncrementSerialActiveFrameCount");
  // Trying to invalidate the tab state while being destroyed could result in a
  // use after free.
  if (IsBeingDestroyed()) {
    return;
  }

  // Notify for UI updates if the state changes.
  serial_active_frame_count_++;
  if (serial_active_frame_count_ == 1) {
    OnCapabilityTypesChanged(WebContentsCapabilityType::kSerial, /*used=*/true);
  }
}

void WebContentsImpl::DecrementSerialActiveFrameCount() {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::DecrementSerialActiveFrameCount");
  // Trying to invalidate the tab state while being destroyed could result in a
  // use after free.
  if (IsBeingDestroyed()) {
    return;
  }

  // Notify for UI updates if the state changes.
  DCHECK_NE(0u, serial_active_frame_count_);
  serial_active_frame_count_--;
  if (serial_active_frame_count_ == 0) {
    OnCapabilityTypesChanged(WebContentsCapabilityType::kSerial,
                             /*used=*/false);
  }
}

void WebContentsImpl::IncrementHidActiveFrameCount() {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::IncrementHidActiveFrameCount");
  // Trying to invalidate the tab state while being destroyed could result in a
  // use after free.
  if (IsBeingDestroyed()) {
    return;
  }

  // Notify for UI updates if the active frame count transitions from zero to
  // non-zero.
  hid_active_frame_count_++;
  if (hid_active_frame_count_ == 1) {
    OnCapabilityTypesChanged(WebContentsCapabilityType::kHID, /*used=*/true);
  }
}

void WebContentsImpl::DecrementHidActiveFrameCount() {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::DecrementHidActiveFrameCount");
  // Trying to invalidate the tab state while being destroyed could result in a
  // use after free.
  if (IsBeingDestroyed()) {
    return;
  }

  // Notify for UI updates if the active frame count transitions from non-zero
  // to zero.
  DCHECK_NE(0u, hid_active_frame_count_);
  hid_active_frame_count_--;
  if (hid_active_frame_count_ == 0) {
    OnCapabilityTypesChanged(WebContentsCapabilityType::kHID, /*used=*/false);
  }
}

void WebContentsImpl::IncrementGeolocationActiveFrameCount() {
  OPTIONAL_TRACE_EVENT0(
      "content", "WebContentsImpl::IncrementGeolocationActiveFrameCount");
  // Trying to invalidate the tab state while being destroyed could result in a
  // use after free.
  if (IsBeingDestroyed()) {
    return;
  }

  // Notify for UI updates if the active frame count transitions from zero to
  // non-zero.
  geolocation_active_frame_count_++;
  if (geolocation_active_frame_count_ == 1) {
    OnCapabilityTypesChanged(WebContentsCapabilityType::kGeolocation,
                             /*used=*/true);
  }
}

void WebContentsImpl::DecrementGeolocationActiveFrameCount() {
  OPTIONAL_TRACE_EVENT0(
      "content", "WebContentsImpl::DecrementGeolocationActiveFrameCount");
  // Trying to invalidate the tab state while being destroyed could result in a
  // use after free.
  if (IsBeingDestroyed()) {
    return;
  }

  // Notify for UI updates if the active frame count transitions from non-zero
  // to zero.
  DCHECK_NE(0u, geolocation_active_frame_count_);
  geolocation_active_frame_count_--;
  if (geolocation_active_frame_count_ == 0) {
    OnCapabilityTypesChanged(WebContentsCapabilityType::kGeolocation,
                             /*used=*/false);
  }
}

void WebContentsImpl::OnCapabilityTypesChanged(
    WebContentsCapabilityType capability_type,
    bool used) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::OnCapabilityTypesChanged");
  NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
  observers_.NotifyObservers(&WebContentsObserver::OnCapabilityTypesChanged,
                             capability_type, used);
}

void WebContentsImpl::IncrementUsbActiveFrameCount() {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::IncrementUsbActiveFrameCount");
  // Trying to invalidate the tab state while being destroyed could result in a
  // use after free.
  if (IsBeingDestroyed()) {
    return;
  }

  // Notify for UI updates if the active frame count transitions from zero to
  // non-zero.
  usb_active_frame_count_++;
  if (usb_active_frame_count_ == 1) {
    OnCapabilityTypesChanged(WebContentsCapabilityType::kUSB, /*used=*/true);
  }
}

void WebContentsImpl::DecrementUsbActiveFrameCount() {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::DecrementUsbActiveFrameCount");
  // Trying to invalidate the tab state while being destroyed could result in a
  // use after free.
  if (IsBeingDestroyed()) {
    return;
  }

  // Notify for UI updates if the active frame count transitions from non-zero
  // to zero.
  DCHECK_NE(0u, usb_active_frame_count_);
  usb_active_frame_count_--;
  if (usb_active_frame_count_ == 0) {
    OnCapabilityTypesChanged(WebContentsCapabilityType::kUSB, /*used=*/false);
  }
}

void WebContentsImpl::IncrementFileSystemAccessHandleCount() {
  OPTIONAL_TRACE_EVENT0(
      "content", "WebContentsImpl::IncrementFileSystemAccessHandleCount");
  // Trying to invalidate the tab state while being destroyed could result in a
  // use after free.
  if (IsBeingDestroyed()) {
    return;
  }

  // Notify for UI updates if the state changes. Need both TYPE_TAB and TYPE_URL
  // to update both the tab-level usage indicator and the usage indicator in the
  // omnibox.
  file_system_access_handle_count_++;
  if (file_system_access_handle_count_ == 1) {
    NotifyNavigationStateChanged(static_cast<content::InvalidateTypes>(
        INVALIDATE_TYPE_TAB | INVALIDATE_TYPE_URL));
  }
}

void WebContentsImpl::DecrementFileSystemAccessHandleCount() {
  OPTIONAL_TRACE_EVENT0(
      "content", "WebContentsImpl::DecrementFileSystemAccessHandleCount");
  // Trying to invalidate the tab state while being destroyed could result in a
  // use after free.
  if (IsBeingDestroyed()) {
    return;
  }

  // Notify for UI updates if the state changes. Need both TYPE_TAB and TYPE_URL
  // to update both the tab-level usage indicator and the usage indicator in the
  // omnibox.
  DCHECK_NE(0u, file_system_access_handle_count_);
  file_system_access_handle_count_--;
  if (file_system_access_handle_count_ == 0) {
    NotifyNavigationStateChanged(static_cast<content::InvalidateTypes>(
        INVALIDATE_TYPE_TAB | INVALIDATE_TYPE_URL));
  }
}

void WebContentsImpl::SetHasPersistentVideo(bool has_persistent_video) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::SetHasPersistentVideo",
                        "has_persistent_video", has_persistent_video,
                        "had_persistent_value", has_persistent_video_);
  if (has_persistent_video_ == has_persistent_video) {
    return;
  }

  has_persistent_video_ = has_persistent_video;
  NotifyPreferencesChanged();
  media_web_contents_observer()->RequestPersistentVideo(has_persistent_video);

  // This is Picture-in-Picture on Android S+.
  if (auto* view = GetRenderWidgetHostView()) {
    static_cast<RenderWidgetHostViewBase*>(view)->SetHasPersistentVideo(
        has_persistent_video);
  }
}

void WebContentsImpl::SetSpatialNavigationDisabled(bool disabled) {
  OPTIONAL_TRACE_EVENT2(
      "content", "WebContentsImpl::SetSpatialNavigationDisabled", "disabled",
      disabled, "was_disabled", is_spatial_navigation_disabled_);
  if (is_spatial_navigation_disabled_ == disabled) {
    return;
  }

  is_spatial_navigation_disabled_ = disabled;
  NotifyPreferencesChanged();
}

#if BUILDFLAG(IS_ANDROID)
void WebContentsImpl::SetStylusHandwritingEnabled(bool enabled) {
  if (stylus_handwriting_enabled_ == enabled) {
    return;
  }
  stylus_handwriting_enabled_ = enabled;
  NotifyPreferencesChanged();
}
#endif  // BUILDFLAG(IS_ANDROID)

PictureInPictureResult WebContentsImpl::EnterPictureInPicture() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::EnterPictureInPicture");
  return delegate_ ? delegate_->EnterPictureInPicture(this)
                   : PictureInPictureResult::kNotSupported;
}

void WebContentsImpl::ExitPictureInPicture() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::ExitPictureInPicture");
  if (delegate_) {
    delegate_->ExitPictureInPicture();
  }
}

void WebContentsImpl::OnXrHasRenderTarget(
    const viz::FrameSinkId& frame_sink_id) {
  xr_render_target_ = frame_sink_id;
  observers_.NotifyObservers(&WebContentsObserver::CaptureTargetChanged);
}

WebContentsImpl::CaptureTarget WebContentsImpl::GetCaptureTarget() {
  // We don't provide a view for the Android AR capturer. This is not a problem
  // because it is currently only used by the MouseCursorOverlayController,
  // which isn't used on Android anyway.
  if (xr_render_target_.is_valid()) {
    return CaptureTarget{.sink_id = xr_render_target_};
  }

  RenderWidgetHostView* host_view = GetRenderWidgetHostView();
  if (!host_view) {
    return {};
  }

  RenderWidgetHostViewBase* base_view =
      static_cast<RenderWidgetHostViewBase*>(host_view);
  return CaptureTarget{.sink_id = base_view->GetFrameSinkId(),
                       .view = host_view->GetNativeView()};
}

#if BUILDFLAG(IS_ANDROID)
void WebContentsImpl::NotifyFindMatchRectsReply(
    int version,
    const std::vector<gfx::RectF>& rects,
    const gfx::RectF& active_rect) {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::NotifyFindMatchRectsReply");
  if (delegate_) {
    delegate_->FindMatchRectsReply(this, version, rects, active_rect);
  }
}
#endif

void WebContentsImpl::SetForceDisableOverscrollContent(bool force_disable) {
  OPTIONAL_TRACE_EVENT1("content",
                        "WebContentsImpl::SetForceDisableOverscrollContent",
                        "force_disable", force_disable);
  force_disable_overscroll_content_ = force_disable;
  if (view_) {
    view_->SetOverscrollControllerEnabled(CanOverscrollContent());
  }
}

bool WebContentsImpl::SetDeviceEmulationSize(const gfx::Size& new_size) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::SetDeviceEmulationSize");
  device_emulation_size_ = new_size;
  RenderWidgetHostView* rwhv = GetPrimaryMainFrame()->GetView();

  const gfx::Size current_size = rwhv->GetViewBounds().size();
  if (view_size_before_emulation_.IsEmpty()) {
    view_size_before_emulation_ = current_size;
  }

  if (current_size != new_size) {
    rwhv->SetSize(new_size);
  }

  return current_size != new_size;
}

void WebContentsImpl::ClearDeviceEmulationSize() {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::ClearDeviceEmulationSize");
  RenderWidgetHostView* rwhv = GetPrimaryMainFrame()->GetView();
  // WebContentsView could get resized during emulation, which also resizes
  // RWHV. If it happens, assume user would like to keep using the size after
  // emulation.
  // TODO(jzfeng): Prohibit resizing RWHV through any other means (at least when
  // WebContentsView size changes).
  if (!view_size_before_emulation_.IsEmpty() && rwhv &&
      rwhv->GetViewBounds().size() == device_emulation_size_) {
    rwhv->SetSize(view_size_before_emulation_);
  }
  device_emulation_size_ = gfx::Size();
  view_size_before_emulation_ = gfx::Size();
}

ForwardingAudioStreamFactory* WebContentsImpl::GetAudioStreamFactory() {
  if (!audio_stream_factory_) {
    audio_stream_factory_ = CreateAudioStreamFactory();
  }
  return audio_stream_factory_.get();
}

std::unique_ptr<ForwardingAudioStreamFactory>
WebContentsImpl::CreateAudioStreamFactory(
    base::PassKey<GuestPageHolderImpl> pass_key) {
  return CreateAudioStreamFactory();
}

std::unique_ptr<ForwardingAudioStreamFactory>
WebContentsImpl::CreateAudioStreamFactory() {
  std::unique_ptr<AudioStreamBrokerFactory> broker_factory;
  if (delegate_) {
    broker_factory = delegate_->CreateAudioStreamBrokerFactory(this);
  }
  if (!broker_factory) {
    broker_factory = AudioStreamBrokerFactory::CreateImpl();
  }
  return std::make_unique<ForwardingAudioStreamFactory>(
      this, std::move(broker_factory));
}

void WebContentsImpl::MediaStartedPlaying(
    const WebContentsObserver::MediaPlayerInfo& media_info,
    const MediaPlayerId& id) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::MediaStartedPlaying");
  observers_.NotifyObservers(&WebContentsObserver::MediaStartedPlaying,
                             media_info, id);
}

void WebContentsImpl::MediaStoppedPlaying(
    const WebContentsObserver::MediaPlayerInfo& media_info,
    const MediaPlayerId& id,
    WebContentsObserver::MediaStoppedReason reason) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::MediaStoppedPlaying");
  observers_.NotifyObservers(&WebContentsObserver::MediaStoppedPlaying,
                             media_info, id, reason);
}

void WebContentsImpl::MediaMetadataChanged(
    const WebContentsObserver::MediaPlayerInfo& media_info,
    const MediaPlayerId& id) {
  observers_.NotifyObservers(&WebContentsObserver::MediaMetadataChanged,
                             media_info, id);
}

void WebContentsImpl::MediaResized(const gfx::Size& size,
                                   const MediaPlayerId& id) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::MediaResized");
  cached_video_sizes_[id] = size;

  observers_.NotifyObservers(&WebContentsObserver::MediaResized, size, id);
}

void WebContentsImpl::MediaEffectivelyFullscreenChanged(bool is_fullscreen) {
  OPTIONAL_TRACE_EVENT1("content",
                        "WebContentsImpl::MediaEffectivelyFullscreenChanged",
                        "is_fullscreen", is_fullscreen);
  observers_.NotifyObservers(
      &WebContentsObserver::MediaEffectivelyFullscreenChanged, is_fullscreen);
}

void WebContentsImpl::MediaDestroyed(const MediaPlayerId& id) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::MediaDestroyed");
  observers_.NotifyObservers(&WebContentsObserver::MediaDestroyed, id);
}

void WebContentsImpl::MediaSessionCreated(MediaSession* media_session) {
  observers_.NotifyObservers(&WebContentsObserver::MediaSessionCreated,
                             media_session);
}

int WebContentsImpl::GetCurrentlyPlayingVideoCount() const {
  return media_web_contents_observer_->GetCurrentlyPlayingVideoCount();
}

std::optional<gfx::Size> WebContentsImpl::GetFullscreenVideoSize() {
  std::optional<MediaPlayerId> id =
      media_web_contents_observer_->GetFullscreenVideoMediaPlayerId();
  if (id) {
    if (auto it = cached_video_sizes_.find(id.value());
        it != cached_video_sizes_.end()) {
      return std::optional<gfx::Size>(it->second);
    }
  }
  return std::nullopt;
}

void WebContentsImpl::AudioContextPlaybackStarted(RenderFrameHostImpl* host,
                                                  int context_id) {
  OPTIONAL_TRACE_EVENT1("content",
                        "WebContentsImpl::AudioContextPlaybackStarted",
                        "render_frame_host", host);
  WebContentsObserver::AudioContextId audio_context_id(host, context_id);
  observers_.NotifyObservers(&WebContentsObserver::AudioContextPlaybackStarted,
                             audio_context_id);
}

void WebContentsImpl::AudioContextPlaybackStopped(RenderFrameHostImpl* host,
                                                  int context_id) {
  OPTIONAL_TRACE_EVENT1("content",
                        "WebContentsImpl::AudioContextPlaybackStopped",
                        "render_frame_host", host);
  WebContentsObserver::AudioContextId audio_context_id(host, context_id);
  observers_.NotifyObservers(&WebContentsObserver::AudioContextPlaybackStopped,
                             audio_context_id);
}

void WebContentsImpl::OnFrameAudioStateChanged(RenderFrameHostImpl* host,
                                               bool is_audible) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::OnFrameAudioStateChanged",
                        "render_frame_host", host, "is_audible", is_audible);
  observers_.NotifyObservers(&WebContentsObserver::OnFrameAudioStateChanged,
                             host, is_audible);
}

void WebContentsImpl::OnFrameVisibilityChanged(
    RenderFrameHostImpl* host,
    blink::mojom::FrameVisibility visibility) {
  OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::OnFrameVisibilityChanged",
                        "render_frame_host", host, "visibility", visibility);
  observers_.NotifyObservers(&WebContentsObserver::OnFrameVisibilityChanged,
                             host, visibility);
}

void WebContentsImpl::OnRemoteSubframeViewportIntersectionStateChanged(
    RenderFrameHostImpl* host,
    const blink::mojom::ViewportIntersectionState&
        viewport_intersection_state) {
  OPTIONAL_TRACE_EVENT2(
      "content",
      "WebContentsImpl::OnRemoteSubframeViewportIntersectionStateChanged",
      "render_frame_host", host, "viewport_intersection_state",
      viewport_intersection_state);
  observers_.NotifyObservers(
      &WebContentsObserver::OnRemoteSubframeViewportIntersectionStateChanged,
      host, viewport_intersection_state);
}

void WebContentsImpl::OnFrameIsCapturingMediaStreamChanged(
    RenderFrameHostImpl* host,
    bool is_capturing_media_stream) {
  observers_.NotifyObservers(
      &WebContentsObserver::OnFrameIsCapturingMediaStreamChanged, host,
      is_capturing_media_stream);
}

// Cf. `GetProspectiveOuterDocument` which applies to the same situation, but is
// for ascending.
std::vector<FrameTreeNode*> WebContentsImpl::GetUnattachedOwnedNodes(
    RenderFrameHostImpl* owner) {
  if (owner->GetParent()) {
    return {};
  }
  BrowserPluginGuestManager* guest_manager =
      GetBrowserContext()->GetGuestManager();
  if (!guest_manager) {
    return {};
  }
  std::vector<FrameTreeNode*> unattached_owned_nodes;
  if (base::FeatureList::IsEnabled(features::kGuestViewMPArch)) {
    guest_manager->ForEachUnattachedGuestPage(
        owner->GetPage(), [&](GuestPageHolder& guest_page) {
          unattached_owned_nodes.push_back(
              static_cast<GuestPageHolderImpl&>(guest_page)
                  .frame_tree()
                  .root());
        });
  } else if (owner == GetPrimaryMainFrame()) {
    guest_manager->ForEachUnattachedGuestContents(
        this, [&](WebContents* guest_contents) {
          unattached_owned_nodes.push_back(
              static_cast<WebContentsImpl*>(guest_contents)
                  ->primary_frame_tree_.root());
        });
  }
  return unattached_owned_nodes;
}

void WebContentsImpl::IsClipboardPasteAllowedByPolicy(
    const ClipboardEndpoint& source,
    const ClipboardEndpoint& destination,
    const ui::ClipboardMetadata& metadata,
    ClipboardPasteData clipboard_paste_data,
    IsClipboardPasteAllowedCallback callback) {
  ++suppress_unresponsive_renderer_count_;
  GetContentClient()->browser()->IsClipboardPasteAllowedByPolicy(
      source, destination, metadata, std::move(clipboard_paste_data),
      base::BindOnce(&WebContentsImpl::IsClipboardPasteAllowedWrapperCallback,
                     weak_factory_.GetWeakPtr(), std::move(callback)));
}

void WebContentsImpl::OnTextCopiedToClipboard(
    RenderFrameHostImpl* render_frame_host,
    const std::u16string& copied_text) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::OnTextCopiedToClipboard",
                        "render_frame_host", render_frame_host);
  observers_.NotifyObservers(&WebContentsObserver::OnTextCopiedToClipboard,
                             render_frame_host, copied_text);
}

void WebContentsImpl::IsClipboardPasteAllowedWrapperCallback(
    IsClipboardPasteAllowedCallback callback,
    std::optional<ClipboardPasteData> clipboard_paste_data) {
  std::move(callback).Run(std::move(clipboard_paste_data));
  --suppress_unresponsive_renderer_count_;
}

std::optional<std::vector<std::u16string>>
WebContentsImpl::GetClipboardTypesIfPolicyApplied(
    const ui::ClipboardSequenceNumberToken& seqno) {
  return GetContentClient()->browser()->GetClipboardTypesIfPolicyApplied(seqno);
}

void WebContentsImpl::BindScreenOrientation(
    RenderFrameHost* rfh,
    mojo::PendingAssociatedReceiver<device::mojom::ScreenOrientation>
        receiver) {
  screen_orientation_provider_->BindScreenOrientation(rfh, std::move(receiver));
}

bool WebContentsImpl::IsTransientActivationRequiredForHtmlFullscreen() {
  // Allow fullscreen if the screen orientation changed in the last 1 second.
  static constexpr base::TimeDelta kMaxInterval = base::Seconds(1);
  const base::TimeDelta delta =
      ui::EventTimeForNow() - last_screen_orientation_change_time_;
  if (delta <= kMaxInterval) {
    return false;
  }

  // Require transient activation shortly after a same-origin WebContents exit.
  RenderFrameHostImpl* host = GetPrimaryMainFrame();
  auto* last_exits = GetFullscreenUserData(GetBrowserContext())->last_exits();
  auto last_exit = last_exits->find(host->GetLastCommittedOrigin());
  constexpr base::TimeDelta kCooldown = base::Seconds(5);
  if (last_exit != last_exits->end() &&
      base::TimeTicks::Now() < last_exit->second + kCooldown) {
    return true;
  }

  // Waive transient activation requirements if Automatic Fullscreen is granted.
  if (IsAutomaticFullscreenGranted(host)) {
    return false;
  }

  return true;
}

bool WebContentsImpl::IsBackForwardCacheSupported() {
  if (!GetDelegate()) {
    return false;
  }
  return GetDelegate()->IsBackForwardCacheSupported(*this);
}

FrameTree* WebContentsImpl::LoadingTree() {
  return &GetPrimaryFrameTree();
}

void WebContentsImpl::DidChangeScreenOrientation() {
  last_screen_orientation_change_time_ = ui::EventTimeForNow();
}

void WebContentsImpl::UpdateWebContentsVisibility(Visibility visibility) {
  OPTIONAL_TRACE_EVENT1("content",
                        "WebContentsImpl::UpdateWebContentsVisibility",
                        "visibility", visibility);
  // Occlusion is disabled when
  // |switches::kDisableBackgroundingOccludedWindowsForTesting| is specified on
  // the command line (to avoid flakiness in browser tests).
  const bool occlusion_is_disabled =
      base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kDisableBackgroundingOccludedWindowsForTesting);
  if (occlusion_is_disabled && visibility == Visibility::OCCLUDED) {
    visibility = Visibility::VISIBLE;
  }

  if (!did_first_set_visible_) {
    if (visibility == Visibility::VISIBLE) {
      // A WebContents created with CreateParams::initially_hidden = false
      // starts with GetVisibility() == Visibility::VISIBLE even though it is
      // not really visible. Call WasShown() when it becomes visible for real as
      // the page load mechanism and some WebContentsObserver rely on that.
      WasShown();
      did_first_set_visible_ = true;
    }

    // Trust the initial visibility of the WebContents and do not switch it to
    // HIDDEN or OCCLUDED before it becomes VISIBLE for real. Doing so would
    // result in destroying resources that would immediately be recreated (e.g.
    // UpdateWebContents(HIDDEN) can be called when a WebContents is added to a
    // hidden window that is about to be shown).

    return;
  }

  if (visibility == visibility_) {
    return;
  }

  UpdateVisibilityAndNotifyPageAndView(visibility);
}

void WebContentsImpl::UpdateOverridingUserAgent() {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::UpdateOverridingUserAgent");
  NotifyPreferencesChanged();
}

void WebContentsImpl::ShowInsecureLocalhostWarningIfNeeded(PageImpl& page) {
  OPTIONAL_TRACE_EVENT0(
      "content", "WebContentsImpl::ShowInsecureLocalhostWarningIfNeeded");

  bool allow_localhost = base::CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kAllowInsecureLocalhost);
  if (!allow_localhost) {
    return;
  }

  RenderFrameHostImpl& frame = page.GetMainDocument();
  NavigationEntry* entry =
      frame.frame_tree()->controller().GetLastCommittedEntry();
  if (!entry || !net::IsLocalhost(entry->GetURL())) {
    return;
  }

  SSLStatus ssl_status = entry->GetSSL();
  if (!net::IsCertStatusError(ssl_status.cert_status)) {
    return;
  }

  frame.AddMessageToConsole(blink::mojom::ConsoleMessageLevel::kWarning,
                            "This site does not have a valid SSL "
                            "certificate! Without SSL, your site's and "
                            "visitors' data is vulnerable to theft and "
                            "tampering. Get a valid SSL certificate before "
                            " releasing your website to the public.");
}

bool WebContentsImpl::IsShowingContextMenuOnPage() const {
  return showing_context_menu_;
}

download::DownloadUrlParameters::RequestHeadersType
WebContentsImpl::ParseDownloadHeaders(const std::string& headers) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::ParseDownloadHeaders",
                        "headers", headers);
  download::DownloadUrlParameters::RequestHeadersType request_headers;
  for (std::string_view key_value : base::SplitStringPiece(
           headers, "\r\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) {
    std::vector<std::string> pair = base::SplitString(
        key_value, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
    if (2ul == pair.size()) {
      request_headers.push_back(make_pair(pair[0], pair[1]));
    }
  }
  return request_headers;
}

void WebContentsImpl::SetOpenerForNewContents(FrameTreeNode* opener,
                                              bool opener_suppressed) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::SetOpenerForNewContents");
  if (opener) {
    FrameTreeNode* new_root = GetPrimaryFrameTree().root();

    // For the "original opener", track the opener's main frame instead, because
    // if the opener is a subframe, the opener tracking could be easily bypassed
    // by spawning from a subframe and deleting the subframe.
    // https://crbug.com/705316
    new_root->SetOriginalOpener(opener->frame_tree().root());
    new_root->SetOpenerDevtoolsFrameToken(
        opener->current_frame_host()->devtools_frame_token());
    opened_by_another_window_ = true;

    if (!opener_suppressed) {
      new_root->SetOpener(opener);
    }
  }
}

void WebContentsImpl::MediaMutedStatusChanged(const MediaPlayerId& id,
                                              bool muted) {
  OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::MediaMutedStatusChanged",
                        "muted", muted);
  observers_.NotifyObservers(&WebContentsObserver::MediaMutedStatusChanged, id,
                             muted);
}

void WebContentsImpl::SetVisibilityForChildViews(bool visible) {
  OPTIONAL_TRACE_EVENT1("content",
                        "WebContentsImpl::SetVisibilityForChildViews",
                        "visible", visible);
  GetPrimaryMainFrame()->SetVisibilityForChildViews(visible);
}

void WebContentsImpl::HandleColorRelatedStateChanges() {
  if (const auto* const theme = ui::NativeTheme::GetInstanceForWeb();
      prefers_reduced_transparency_ != theme->prefers_reduced_transparency() ||
      inverted_colors_ != theme->inverted_colors() ||
      GetContentClient()
          ->browser()
          ->WebPreferencesNeedUpdateForColorRelatedStateChanges(
              *this, *GetPrimaryMainFrame()->GetSiteInstance())) {
    NotifyPreferencesChanged();
  }

  // Update color providers after applying any pending WebPreferences changes.
  // This is done because WebPreferences changes (e.g. `in_forced_colors`) might
  // not trigger an invalidation in Blink, but color provider changes will
  // always trigger invalidation. Therefore, we want to update color providers
  // after we have the right states for the web preferences so we can use the
  // right color providers in Blink to paint. This also handles scenarios where
  // the forced colors state remains the same, but the `forced_colors_map` is
  // updated due to changes in the forced colors mode theme.
  if (blink::ColorProviderColorMaps color_maps = GetColorProviderColorMaps();
      color_maps_ != color_maps) {
    color_maps_.swap(color_maps);
    ExecutePageBroadcastMethodForAllPages([this](RenderViewHostImpl* rvh) {
      if (auto& broadcast = rvh->GetAssociatedPageBroadcast()) {
        broadcast->UpdateColorProviders(color_maps_);
      }
    });
  }
}

void WebContentsImpl::OnNativeThemeUpdated(ui::NativeTheme* observed_theme) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::OnNativeThemeUpdated");
  DCHECK_EQ(observed_theme, ui::NativeTheme::GetInstanceForWeb());

  HandleColorRelatedStateChanges();

  const auto caret_blink_interval = observed_theme->caret_blink_interval();
#if BUILDFLAG(IS_CHROMEOS)
  const auto use_overlay_scrollbar = observed_theme->use_overlay_scrollbar();
#endif
  bool renderer_preference_changed = false;
  if (renderer_preferences_.caret_blink_interval != caret_blink_interval) {
    renderer_preferences_.caret_blink_interval = caret_blink_interval;
    renderer_preference_changed = true;
  }
#if BUILDFLAG(IS_CHROMEOS)
  if (renderer_preferences_.use_overlay_scrollbar != use_overlay_scrollbar) {
    renderer_preferences_.use_overlay_scrollbar = use_overlay_scrollbar;
    renderer_preference_changed = true;
  }
#endif

  if (renderer_preference_changed) {
    SyncRendererPrefs();
  }
}

void WebContentsImpl::OnCaptionStyleUpdated() {
  NotifyPreferencesChanged();
}

void WebContentsImpl::OnColorProviderChanged() {
  // OnColorProviderChanged() might have been triggered as the result of the
  // observed source being reset. If this is the case fallback to the default
  // source.
  if (!GetColorProviderSource()) {
    // This will synchronously call `OnColorProviderChanged()` again.
    SetColorProviderSource(DefaultColorProviderSource::GetInstance());
    return;
  }

  observers_.NotifyObservers(&WebContentsObserver::OnColorProviderChanged);

  HandleColorRelatedStateChanges();
}

const ui::ColorProvider& WebContentsImpl::GetColorProvider() const {
  auto* source = GetColorProviderSource();
  DCHECK(source);
  auto* color_provider = source->GetColorProvider();
  DCHECK(color_provider);
  return *color_provider;
}

void WebContentsImpl::OnSlowWebPreferenceChanged() {
  OnWebPreferencesChanged();
}

blink::mojom::FrameWidgetInputHandler*
WebContentsImpl::GetFocusedFrameWidgetInputHandler() {
  auto* focused_render_widget_host =
      GetFocusedRenderWidgetHost(GetPrimaryMainFrame()->GetRenderWidgetHost());
  if (!focused_render_widget_host) {
    return nullptr;
  }
  return focused_render_widget_host->GetFrameWidgetInputHandler();
}

ukm::SourceId WebContentsImpl::GetCurrentPageUkmSourceId() {
  return GetPrimaryMainFrame()->GetPageUkmSourceId();
}

void WebContentsImpl::ForEachRenderViewHost(
    ForEachRenderViewHostTypes view_mask,
    RenderViewHostIterationCallback on_render_view_host) {
  std::set<RenderViewHostImpl*> render_view_hosts;

  if ((view_mask & (ForEachRenderViewHostTypes::kPrerenderViews |
                    ForEachRenderViewHostTypes::kActiveViews)) != 0) {
    ForEachFrameTree([view_mask, &render_view_hosts](FrameTree& frame_tree) {
      // Check the view masks.
      if (frame_tree.is_prerendering()) {
        // We are in a prerendering page.
        if ((view_mask & ForEachRenderViewHostTypes::kPrerenderViews) == 0) {
          return;
        }
      } else {
        // We are in an active page.
        if ((view_mask & ForEachRenderViewHostTypes::kActiveViews) == 0) {
          return;
        }
      }
      frame_tree.ForEachRenderViewHost(
          [&render_view_hosts](RenderViewHostImpl* rvh) {
            render_view_hosts.insert(rvh);
          });
    });
  }

  if ((view_mask & ForEachRenderViewHostTypes::kBackForwardCacheViews) != 0) {
    // Add RenderViewHostImpls in BackForwardCache.
    const auto& entries = GetController().GetBackForwardCache().GetEntries();
    for (const auto& entry : entries) {
      for (const auto& render_view : entry->render_view_hosts()) {
        render_view_hosts.insert(&*render_view);
      }
    }
  }

  for (auto* render_view_host : render_view_hosts) {
    on_render_view_host.Run(render_view_host);
  }
}

void WebContentsImpl::NotifyPageBecamePrimary(PageImpl& page) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::PrimaryPageChanged");

  DCHECK_EQ(&page, &GetPrimaryPage());

#if BUILDFLAG(IS_ANDROID)
  // Apply the cached subframe importance if it is set. This is needed for
  // pages restored from back/forward cache. Note that we don't need to clear
  // importance for non-primary pages because the importance is ignored at
  // RenderWidgetHostImpl::GetPriority() and updated when it becomes inactive.
  if (base::FeatureList::IsEnabled(features::kSubframeImportance)) {
    ApplyPrimaryPageSubframeImportance();
  }
#endif

  // Clear |save_package_| since the primary page changed.
  if (save_package_) {
    save_package_->ClearPage();
    save_package_.reset();
  }

  // Sync draggable regions.
  SetSupportsDraggableRegions(supports_draggable_regions_);

  observers_.NotifyObservers(&WebContentsObserver::PrimaryPageChanged, page);
}

bool WebContentsImpl::IsPageInPreviewMode() const {
  return IsInPreviewMode();
}

void WebContentsImpl::CancelPreviewByMojoBinderPolicy(
    const std::string& interface_name) {
  if (delegate_) {
    delegate_->CancelPreview(
        PreviewCancelReason::BlockedByMojoBinderPolicy(interface_name));
  }
}

void WebContentsImpl::OnWebApiWindowResizableChanged() {
  delegate_->OnWebApiWindowResizableChanged();
}

FrameTreeNodeId WebContentsImpl::GetOuterDelegateFrameTreeNodeId() {
  return node_.outer_contents_frame_tree_node_id();
}

// Cf. `GetUnattachedOwnedNodes` which applies to the same situation, but is for
// descending.
RenderFrameHostImpl* WebContentsImpl::GetProspectiveOuterDocument() {
  // If the outer WebContents is already known, then there was no need to call
  // this method.
  DCHECK(!GetOuterWebContents());

  RenderFrameHostImpl* unattached_guest_owner =
      browser_plugin_guest_
          ? browser_plugin_guest_->GetProspectiveOuterDocument()
          : nullptr;
  if (unattached_guest_owner) {
    return unattached_guest_owner;
  }

  return nullptr;
}

void WebContentsImpl::RenderFrameHostStateChanged(
    RenderFrameHost* render_frame_host,
    LifecycleState old_state,
    LifecycleState new_state) {
  DCHECK_NE(old_state, new_state);
  OPTIONAL_TRACE_EVENT("content",
                       "WebContentsImpl::RenderFrameHostStateChanged",
                       "render_frame_host", render_frame_host, "old_state",
                       old_state, "new_state", new_state);

#if BUILDFLAG(IS_ANDROID)
  if (old_state == LifecycleState::kActive && !render_frame_host->GetParent()) {
    // TODO(sreejakshetty): Remove this reset when ColorChooserHolder becomes
    // per-frame.
    // Close the color chooser popup when RenderFrameHost changes state from
    // kActive.
    color_chooser_holder_.reset();
  }
#endif  // BUILDFLAG(IS_ANDROID)

  observers_.NotifyObservers(&WebContentsObserver::RenderFrameHostStateChanged,
                             render_frame_host, old_state, new_state);
}

void WebContentsImpl::DecrementCapturerCount(bool stay_hidden,
                                             bool stay_awake,
                                             bool is_activity) {
  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::DecrementCapturerCount");
  if (stay_hidden) {
    --hidden_capturer_count_;
  } else {
    --visible_capturer_count_;
  }
  if (stay_awake) {
    --stay_awake_capturer_count_;
  }
  DCHECK_GE(hidden_capturer_count_, 0);
  DCHECK_GE(visible_capturer_count_, 0);
  DCHECK_GE(stay_awake_capturer_count_, 0);

  if (IsBeingDestroyed()) {
    return;
  }

  view_->OnCapturerCountChanged();

  const bool is_being_captured = IsBeingCaptured();
  if (!is_being_captured) {
    const gfx::Size old_size = preferred_size_for_capture_;
    preferred_size_for_capture_ = gfx::Size();
    OnPreferredSizeChanged(old_size);
  }

  if (capture_wake_lock_ &&
      (!is_being_captured || !stay_awake_capturer_count_)) {
    capture_wake_lock_->CancelWakeLock();
  }

  UpdateVisibilityAndNotifyPageAndView(GetVisibility(), is_activity);
}

void WebContentsImpl::NotifyPrimaryMainFrameProcessIsAlive() {
  // The WebContents tracks the process state for the primary main frame's
  // renderer.
  // Consider renderer as terminated when exited with any termination status.
  bool was_renderer_terminated = primary_main_frame_process_status_ !=
                                 base::TERMINATION_STATUS_STILL_RUNNING;
  SetPrimaryMainFrameProcessStatus(base::TERMINATION_STATUS_STILL_RUNNING, 0);
  // Restore the focus to the tab (otherwise the focus will be on the top
  // window).
  if (was_renderer_terminated && !FocusLocationBarByDefault()) {
    if (!delegate_ || delegate_->ShouldFocusPageAfterCrash(this)) {
      view_->Focus();
    }
  }
}

void WebContentsImpl::UpdateBrowserControlsState(
    cc::BrowserControlsState constraints,
    cc::BrowserControlsState current,
    bool animate,
    const std::optional<cc::BrowserControlsOffsetTagModifications>&
        offset_tag_modifications) {
  // Browser controls should be synchronised with the scroll state. Therefore,
  // they are controlled from the renderer by the main RenderFrame(Host).
  GetPrimaryPage().UpdateBrowserControlsState(constraints, current, animate,
                                              offset_tag_modifications);
}

void WebContentsImpl::SetSupportsDraggableRegions(
    bool supports_draggable_regions) {
  supports_draggable_regions_ = supports_draggable_regions;
  ExecutePageBroadcastMethod(
      [supports_draggable_regions](RenderViewHostImpl* rvh) {
        if (auto& broadcast = rvh->GetAssociatedPageBroadcast()) {
          broadcast->SetSupportsDraggableRegions(supports_draggable_regions);
        }
      });
}

void WebContentsImpl::SetV8CompileHints(base::ReadOnlySharedMemoryRegion data) {
  GetPrimaryMainFrame()->GetAssociatedLocalMainFrame()->SetV8CompileHints(
      std::move(data));
}

void WebContentsImpl::SetTabSwitchStartTime(base::TimeTicks start_time,
                                            bool destination_is_loaded) {
  GetVisibleTimeRequestTrigger().UpdateRequest(
      start_time, destination_is_loaded,
      /*show_reason_tab_switching=*/true,
      /*show_reason_bfcache_restore=*/false);
}

bool WebContentsImpl::IsInPreviewMode() const {
  return is_in_preview_mode_;
}

void WebContentsImpl::WillActivatePreviewPage() {
  CHECK(is_in_preview_mode_);
  is_in_preview_mode_ = false;
}

void WebContentsImpl::ActivatePreviewPage() {
  TRACE_EVENT0("content", "WebContentsImpl::ActivatePreviewPage");

  // WillActivatePreviewPage() should be called to reset it beforehand.
  CHECK(!is_in_preview_mode_);

  PageImpl& preview_page = GetPrimaryPage();
  preview_page.SetActivationStartTime(base::TimeTicks::Now());

  // TODO(b:299240273): Gather all relevant RVHs.
  StoredPage::RenderViewHostImplSafeRefSet render_view_hosts;
  render_view_hosts.insert(GetRenderViewHost()->GetSafeRef());

  preview_page.Activate(
      PageImpl::ActivationType::kPreview, render_view_hosts, std::nullopt,
      base::BindOnce(&WebContentsImpl::DidActivatePreviewedPage,
                     weak_factory_.GetWeakPtr()));
}

VisibleTimeRequestTrigger& WebContentsImpl::GetVisibleTimeRequestTrigger() {
  return visible_time_request_trigger_;
}

gfx::mojom::DelegatedInkPointRenderer* WebContentsImpl::GetDelegatedInkRenderer(
    ui::Compositor* compositor) {
  if (!delegated_ink_point_renderer_.is_bound()) {
    // The remote can't be bound if the compositor is null, so bail if
    // that is the case so we don't crash by trying to use an unbound
    // remote.
    if (!compositor) {
      return nullptr;
    }

    TRACE_EVENT_INSTANT0("delegated_ink_trails",
                         "Binding mojo interface for delegated ink points.",
                         TRACE_EVENT_SCOPE_THREAD);
    compositor->SetDelegatedInkPointRenderer(
        delegated_ink_point_renderer_.BindNewPipeAndPassReceiver());
    delegated_ink_point_renderer_.reset_on_disconnect();
  }
  return delegated_ink_point_renderer_.get();
}

void WebContentsImpl::OnInputIgnored(const blink::WebInputEvent& event) {
#if BUILDFLAG(IS_ANDROID)
  if (auto* animation_manager =
          static_cast<BackForwardTransitionAnimationManagerAndroid*>(
              GetBackForwardTransitionAnimationManager())) {
    animation_manager->MaybeRecordIgnoredInput(event);
  }
#endif
}

#if BUILDFLAG(IS_ANDROID)
float WebContentsImpl::GetCurrentTouchSequenceYOffset() {
  ui::ViewAndroid* view_android = GetNativeView();
  return view_android->event_forwarder()->GetCurrentTouchSequenceYOffset();
}
#endif

std::unique_ptr<PrefetchHandle> WebContentsImpl::StartPrefetch(
    const GURL& prefetch_url,
    bool use_prefetch_proxy,
    const std::string& embedder_histogram_suffix,
    const blink::mojom::Referrer& referrer,
    const std::optional<url::Origin>& referring_origin,
    std::optional<net::HttpNoVarySearchData> no_vary_search_hint,
    std::optional<PrefetchPriority> priority,
    scoped_refptr<PreloadPipelineInfo> preload_pipeline_info,
    base::WeakPtr<PreloadingAttempt> attempt,
    PreloadingHoldbackStatus holdback_status_override,
    std::optional<base::TimeDelta> ttl) {
  PrefetchService* prefetch_service =
      BrowserContextImpl::From(GetBrowserContext())->GetPrefetchService();
  if (!prefetch_service) {
    return nullptr;
  }

  PrefetchType prefetch_type(PreloadingTriggerType::kEmbedder,
                             use_prefetch_proxy);
  auto request = PrefetchRequest::CreateBrowserInitiated(
      *this, prefetch_url, prefetch_type, embedder_histogram_suffix, referrer,
      referring_origin, std::move(no_vary_search_hint), std::move(priority),
      std::move(preload_pipeline_info), std::move(attempt),
      holdback_status_override, std::move(ttl));

  return prefetch_service->AddPrefetchRequestWithHandle(std::move(request));
}

std::unique_ptr<PrerenderHandle> WebContentsImpl::StartPrerendering(
    const GURL& prerendering_url,
    PreloadingTriggerType trigger_type,
    const std::string& embedder_histogram_suffix,
    net::HttpRequestHeaders additional_headers,
    std::optional<net::HttpNoVarySearchData> no_vary_search_hint,
    ui::PageTransition page_transition,
    bool should_warm_up_compositor,
    bool should_prepare_paint_tree,
    PreloadingHoldbackStatus holdback_status_override,
    scoped_refptr<PreloadPipelineInfo> preload_pipeline_info,
    PreloadingAttempt* preloading_attempt,
    base::RepeatingCallback<bool(const GURL&,
                                 const std::optional<UrlMatchType>&)>
        url_match_predicate,
    base::RepeatingCallback<void(NavigationHandle&)>
        prerender_navigation_handle_callback,
    bool allow_reuse) {
  PrerenderAttributes attributes(
      prerendering_url, trigger_type, embedder_histogram_suffix,
      /*speculation_rules_params=*/std::nullopt, content::Referrer(),
      no_vary_search_hint,
      /*initiator_render_frame_host=*/nullptr, GetWeakPtr(), page_transition,
      should_warm_up_compositor, should_prepare_paint_tree,
      blink::mojom::SpeculationAction::kPrerender,
      std::move(url_match_predicate),
      std::move(prerender_navigation_handle_callback),
      base::WrapRefCounted(
          static_cast<PreloadPipelineInfoImpl*>(preload_pipeline_info.get())),
      allow_reuse);
#if BUILDFLAG(IS_ANDROID)
  attributes.additional_headers = std::move(additional_headers);
#else
  CHECK(additional_headers.IsEmpty())
      << "additional_headers is supported only on Android WebView.";
#endif  // BUILDFLAG(IS_ANDROID)
  attributes.holdback_status_override = holdback_status_override;

  FrameTreeNodeId frame_tree_node_id =
      GetPrerenderHostRegistry()->CreateAndStartHost(attributes,
                                                     preloading_attempt);

  if (frame_tree_node_id) {
    return std::make_unique<PrerenderHandleImpl>(
        GetPrerenderHostRegistry()->GetWeakPtr(), frame_tree_node_id,
        prerendering_url, std::move(no_vary_search_hint));
  }
  return nullptr;
}

void WebContentsImpl::CancelAllPrerendering() {
  GetPrerenderHostRegistry()->CancelAllHosts(
      PrerenderFinalStatus::kAllPrerenderingCanceled);
}

bool WebContentsImpl::IsAllowedToStartPrerendering() {
  return GetPrerenderHostRegistry()->IsAllowedToStartPrerenderingForEmbedder();
}

void WebContentsImpl::BackNavigationLikely(PreloadingPredictor predictor,
                                           WindowOpenDisposition disposition) {
  CHECK(!IsBeingDestroyed());

  // See the comment of `last_back_navigation_hint_time_` for why this cooldown
  // exists. The choice of 5 seconds is arbitrary.
  constexpr base::TimeDelta kCooldown = base::Seconds(5);
  base::TimeTicks now = ui::EventTimeForNow();
  if (now - last_back_navigation_hint_time_ < kCooldown) {
    return;
  }
  last_back_navigation_hint_time_ = now;

  if (disposition != WindowOpenDisposition::CURRENT_TAB) {
    RecordPrerenderBackNavigationEligibility(
        predictor, PrerenderBackNavigationEligibility::kTargetingOtherWindow,
        nullptr);
    return;
  }

  GetPrerenderHostRegistry()->BackNavigationLikely(predictor);
}

void WebContentsImpl::SetOwnerLocationForDebug(
    std::optional<base::Location> owner_location) {
  ownership_location_ = owner_location;
}

void WebContentsImpl::AboutToBeDiscarded(WebContents* new_contents) {
  observers_.NotifyObservers(&WebContentsObserver::AboutToBeDiscarded,
                             new_contents);
}

void WebContentsImpl::NotifyWasDiscarded() {
  observers_.NotifyObservers(&WebContentsObserver::WasDiscarded);
}

base::ScopedClosureRunner WebContentsImpl::CreateDisallowCustomCursorScope(
    int max_dimension_dips) {
  auto* render_widget_host_base = GetPrimaryMainFrame()
                                      ->GetRenderWidgetHost()
                                      ->GetRenderWidgetHostViewBase();

  // It's possible for |render_widget_host_base| to be null if the renderer
  // crashed. To avoid race conditions, null-check here. See crbug.com/1421552
  // as well.
  if (!render_widget_host_base) {
    return base::ScopedClosureRunner();
  }

  auto* cursor_manager = render_widget_host_base->GetCursorManager();
  return cursor_manager->CreateDisallowCustomCursorScope(max_dimension_dips);
}

bool WebContentsImpl::CancelPrerendering(FrameTreeNode* frame_tree_node,
                                         PrerenderFinalStatus final_status) {
  if (!frame_tree_node) {
    return false;
  }

  DCHECK_EQ(this, FromFrameTreeNode(frame_tree_node));

  // A prerendered page is identified by its root FrameTreeNode id, so if the
  // given `frame_tree_node` is in any way embedded, we need to iterate up to
  // the prerender root.
  if (frame_tree_node->GetParentOrOuterDocumentOrEmbedder()) {
    return frame_tree_node->GetParentOrOuterDocumentOrEmbedder()
        ->CancelPrerendering(PrerenderCancellationReason(final_status));
  }
  return GetPrerenderHostRegistry()->CancelHost(
      frame_tree_node->frame_tree_node_id(), final_status);
}

ui::mojom::VirtualKeyboardMode WebContentsImpl::GetVirtualKeyboardMode() const {
  return primary_frame_tree_.root()
      ->current_frame_host()
      ->GetPage()
      .virtual_keyboard_mode();
}

void WebContentsImpl::SetOverscrollNavigationEnabled(bool enabled) {
  GetView()->SetOverscrollControllerEnabled(enabled);
}

network::mojom::AttributionSupport WebContentsImpl::GetAttributionSupport() {
  ContentBrowserClient::AttributionReportingOsRegistrars reportTypes =
      AttributionOsLevelManager::GetAttributionReportingOsRegistrars(this);

  return AttributionManager::GetAttributionSupport(
      reportTypes.source_registrar ==
          AttributionReportingOsRegistrar::kDisabled &&
      reportTypes.trigger_registrar ==
          AttributionReportingOsRegistrar::kDisabled);
}

void WebContentsImpl::UpdateAttributionSupportRenderer() {
  OPTIONAL_TRACE_EVENT0("content",
                        "WebContentsImpl::UpdateAttributionSupportRenderer");

  network::mojom::AttributionSupport support = GetAttributionSupport();
  ExecutePageBroadcastMethodForAllPages([support](RenderViewHostImpl* rvh) {
    if (auto& broadcast = rvh->GetAssociatedPageBroadcast()) {
      broadcast->SetPageAttributionSupport(support);
    }
  });
}

BackForwardTransitionAnimationManager*
WebContentsImpl::GetBackForwardTransitionAnimationManager() {
  return GetView()->GetBackForwardTransitionAnimationManager();
}

#if BUILDFLAG(IS_ANDROID)
void WebContentsImpl::SetLongPressLinkSelectText(bool enabled) {
  if (long_press_link_select_text_ == enabled) {
    return;
  }
  long_press_link_select_text_ = enabled;
  NotifyPreferencesChanged();
}

void WebContentsImpl::SetCanAcceptLoadDrops(bool enabled) {
  if (renderer_preferences_.can_accept_load_drops == enabled) {
    return;
  }
  renderer_preferences_.can_accept_load_drops = enabled;
  SyncRendererPrefs();
}

bool WebContentsImpl::GetCanAcceptLoadDropsForTesting() {
  return renderer_preferences_.can_accept_load_drops;
}

#endif

net::handles::NetworkHandle WebContentsImpl::GetTargetNetwork() {
  return target_network_;
}

// static
void WebContentsImpl::UpdateAttributionSupportAllRenderers() {
  for (WebContentsImpl* web_contents : GetAllWebContents()) {
    web_contents->UpdateAttributionSupportRenderer();
  }
}

void WebContentsImpl::GetMediaCaptureRawDeviceIdsOpened(
    blink::mojom::MediaStreamType type,
    base::OnceCallback<void(std::vector<std::string>)> callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  CHECK(type == blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE ||
        type == blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE);

  MediaStreamManager* media_stream_manager =
      BrowserMainLoop::GetInstance()->media_stream_manager();
  if (!media_stream_manager) {
    std::move(callback).Run({});
    return;
  }

  media_stream_manager->GetRawDeviceIdsOpenedForFrame(
      GetPrimaryMainFrame(), type,
      base::BindPostTaskToCurrentDefault(std::move(callback)));
}

void WebContentsImpl::WarmUpAndroidSpareRenderer() {
  if (GetBrowserContext()->ShutdownStarted()) {
    return;
  }
  if (!GetLastCommittedURL().SchemeIsHTTPOrHTTPS() &&
      features::kAndroidSpareRendererOnlyWarmupAfterWebPageLoaded.Get()) {
    return;
  }
  int renderer_timeout_seconds =
      features::kAndroidSpareRendererTimeoutSeconds.Get();
  if (renderer_timeout_seconds < 0) {
    SpareRenderProcessHostManagerImpl::Get().WarmupSpare(GetBrowserContext());
  } else {
    base::TimeDelta timeout = base::Seconds(renderer_timeout_seconds);
    SpareRenderProcessHostManagerImpl::Get().WarmupSpare(GetBrowserContext(),
                                                         timeout);
  }
}

void WebContentsImpl::SetPartitionedPopinOpenerOnNewWindowIfNeeded(
    WebContentsImpl* new_window,
    const mojom::CreateNewWindowParams& params,
    RenderFrameHostImpl* opener) {
  // We should not take action if the feature is disabled.
  if (!base::FeatureList::IsEnabled(blink::features::kPartitionedPopins)) {
    return;
  }

  // All popins should be counted as popups to ensure proper UX treatment.
  if (!params.features->is_partitioned_popin || !new_window->is_popup_) {
    return;
  }

  PartitionedPopinsController::CreateForWebContents(
      static_cast<WebContentsImpl*>(opener->delegate()));
  new_window->partitioned_popin_opener_ = opener->GetWeakPtr();
  new_window->partitioned_popin_opener_properties_ =
      PartitionedPopinOpenerProperties(
          opener->GetMainFrame()->GetLastCommittedOrigin(),
          opener->ComputeSiteForCookies(),
          opener->GetStorageKey().ancestor_chain_bit());
  opened_partitioned_popin_ = new_window->GetWeakPtr();
}

}  // namespace content
