// 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/gpu/gpu_process_host.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/android/scoped_service_binding_batch.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);

  // Batch service binding updates for the renderer processes of the main frame
  // and the subframes.
  base::android::ScopedServiceBindingBatch scoped_service_binding_batch;

  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());
  }

  // Notify the OS that the workload is about to increase for main frame
  // navigations only. This a trade off between latency and power - we don't
  // want to do it for every navigation.
  if (navigation_handle->IsInMainFrame()) {
    auto* gpu_process_host =
        GpuProcessHost::Get(GPU_PROCESS_KIND_SANDBOXED, /*force_create=*/false);
    if (gpu_process_host) {
      auto* host = gpu_process_host->gpu_host();
      if (host) {
        host->NotifyWorkloadIncrease();
      }
    }
  }

  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
