// 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 "chrome/browser/ui/browser.h"

#include <stddef.h>

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

#include "base/base_paths.h"
#include "base/check_deref.h"
#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/user_metrics.h"
#include "base/notimplemented.h"
#include "base/process/process_info.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/actor/actor_keyed_service.h"
#include "chrome/browser/actor/execution_engine.h"
#include "chrome/browser/app_mode/app_mode_utils.h"
#include "chrome/browser/background/background_contents.h"
#include "chrome/browser/background/background_contents_service.h"
#include "chrome/browser/background/background_contents_service_factory.h"
#include "chrome/browser/bookmarks/bookmark_model_factory.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/buildflags.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/content_settings/mixed_content_settings_tab_helper.h"
#include "chrome/browser/content_settings/page_specific_content_settings_delegate.h"
#include "chrome/browser/content_settings/sound_content_setting_observer.h"
#include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
#include "chrome/browser/defaults.h"
#include "chrome/browser/devtools/devtools_toggle_action.h"
#include "chrome/browser/devtools/devtools_window.h"
#include "chrome/browser/download/download_core_service.h"
#include "chrome/browser/download/download_core_service_factory.h"
#include "chrome/browser/extensions/extension_ui_util.h"
#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/extensions/tab_helper.h"
#include "chrome/browser/file_select_helper.h"
#include "chrome/browser/first_run/first_run.h"
#include "chrome/browser/headless/headless_mode_util.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/lifetime/browser_shutdown.h"
#include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
#include "chrome/browser/picture_in_picture/picture_in_picture_window_manager.h"
#include "chrome/browser/policy/developer_tools_policy_handler.h"
#include "chrome/browser/prefs/incognito_mode_prefs.h"
#include "chrome/browser/preloading/preloading_prefs.h"
#include "chrome/browser/printing/background_printing_manager.h"
#include "chrome/browser/profiles/keep_alive/profile_keep_alive_types.h"
#include "chrome/browser/profiles/keep_alive/scoped_profile_keep_alive.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_destroyer.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/profiles/profile_metrics.h"
#include "chrome/browser/profiles/profiles_state.h"
#include "chrome/browser/repost_form_warning_controller.h"
#include "chrome/browser/search/search.h"
#include "chrome/browser/sessions/app_session_service.h"
#include "chrome/browser/sessions/app_session_service_factory.h"
#include "chrome/browser/sessions/session_restore.h"
#include "chrome/browser/sessions/session_service.h"
#include "chrome/browser/sessions/session_service_factory.h"
#include "chrome/browser/sessions/session_service_lookup.h"
#include "chrome/browser/sessions/session_tab_helper_factory.h"
#include "chrome/browser/sessions/tab_restore_service_factory.h"
#include "chrome/browser/tab_contents/tab_util.h"
#include "chrome/browser/themes/theme_service.h"
#include "chrome/browser/themes/theme_service_factory.h"
#include "chrome/browser/ui/blocked_content/chrome_popup_navigation_delegate.h"
#include "chrome/browser/ui/blocked_content/framebust_block_tab_helper.h"
#include "chrome/browser/ui/bookmarks/bookmark_bar_controller.h"
#include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h"
#include "chrome/browser/ui/bookmarks/bookmark_utils.h"
#include "chrome/browser/ui/browser_command_controller.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_dialogs.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_live_tab_context.h"
#include "chrome/browser/ui/browser_manager_service.h"
#include "chrome/browser/ui/browser_manager_service_factory.h"
#include "chrome/browser/ui/browser_navigator.h"
#include "chrome/browser/ui/browser_navigator_params.h"
#include "chrome/browser/ui/browser_select_file_dialog_controller.h"
#include "chrome/browser/ui/browser_tab_strip_model_delegate.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/browser_ui_prefs.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/browser_window/public/browser_window_features.h"
#include "chrome/browser/ui/browser_window/public/browser_window_interface_iterator.h"
#include "chrome/browser/ui/browser_window/public/create_browser_window.h"
#include "chrome/browser/ui/browser_window/public/desktop_browser_window_capabilities.h"
#include "chrome/browser/ui/chrome_pages.h"
#include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h"
#include "chrome/browser/ui/exclusive_access/fullscreen_controller.h"
#include "chrome/browser/ui/exclusive_access/pointer_lock_controller.h"
#include "chrome/browser/ui/find_bar/find_bar_controller.h"
#include "chrome/browser/ui/global_error/global_error.h"
#include "chrome/browser/ui/global_error/global_error_service.h"
#include "chrome/browser/ui/global_error/global_error_service_factory.h"
#include "chrome/browser/ui/location_bar/location_bar.h"
#include "chrome/browser/ui/page_action/page_action_icon_type.h"
#include "chrome/browser/ui/sad_tab.h"
#include "chrome/browser/ui/search/search_tab_helper.h"
#include "chrome/browser/ui/signin/cookie_clear_on_exit_migration_notice.h"
#include "chrome/browser/ui/singleton_tabs.h"
#include "chrome/browser/ui/status_bubble.h"
#include "chrome/browser/ui/tab_contents/core_tab_helper.h"
#include "chrome/browser/ui/tab_dialogs.h"
#include "chrome/browser/ui/tab_helpers.h"
#include "chrome/browser/ui/tab_modal_confirm_dialog.h"
#include "chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.h"
#include "chrome/browser/ui/tabs/tab_enums.h"
#include "chrome/browser/ui/tabs/tab_group_model.h"
#include "chrome/browser/ui/tabs/tab_menu_model.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/tabs/tab_utils.h"
#include "chrome/browser/ui/ui_features.h"
#include "chrome/browser/ui/unload_controller.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/frame/contents_web_view.h"
#include "chrome/browser/ui/views/frame/multi_contents_view.h"
#include "chrome/browser/ui/views/status_bubble_views.h"
#include "chrome/browser/ui/web_applications/app_browser_controller.h"
#include "chrome/browser/ui/webui/signin/login_ui_service.h"
#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
#include "chrome/browser/ui/window_sizer/window_sizer.h"
#include "chrome/browser/web_applications/web_app_provider.h"
#include "chrome/browser/web_applications/web_app_registrar.h"
#include "chrome/browser/web_applications/web_app_tab_helper.h"
#include "chrome/browser/web_applications/web_app_utils.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "chrome/common/webui_url_constants.h"
#include "chrome/grit/branded_strings.h"
#include "chrome/grit/generated_resources.h"
#include "components/blocked_content/list_item_position.h"
#include "components/blocked_content/popup_blocker.h"
#include "components/blocked_content/popup_blocker_tab_helper.h"
#include "components/blocked_content/popup_tracker.h"
#include "components/bookmarks/browser/bookmark_model.h"
#include "components/bookmarks/browser/bookmark_utils.h"
#include "components/bookmarks/common/bookmark_pref_names.h"
#include "components/captive_portal/core/buildflags.h"
#include "components/content_settings/browser/page_specific_content_settings.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/custom_handlers/protocol_handler.h"
#include "components/custom_handlers/protocol_handler_registry.h"
#include "components/custom_handlers/register_protocol_handler_permission_request.h"
#include "components/favicon/content/content_favicon_driver.h"
#include "components/find_in_page/find_tab_helper.h"
#include "components/headless/console_message_logger/headless_console_message_logger.h"
#include "components/infobars/content/content_infobar_manager.h"
#include "components/javascript_dialogs/tab_modal_dialog_manager.h"
#include "components/keep_alive_registry/keep_alive_registry.h"
#include "components/keep_alive_registry/keep_alive_types.h"
#include "components/keep_alive_registry/scoped_keep_alive.h"
#include "components/page_load_metrics/browser/metrics_web_contents_observer.h"
#include "components/page_load_metrics/common/page_load_metrics.mojom.h"
#include "components/paint_preview/buildflags/buildflags.h"
#include "components/permissions/permission_request_manager.h"
#include "components/prefs/pref_service.h"
#include "components/saved_tab_groups/public/tab_group_sync_service.h"
#include "components/sessions/content/session_tab_helper.h"
#include "components/sessions/core/session_types.h"
#include "components/sessions/core/tab_restore_service.h"
#include "components/startup_metric_utils/browser/startup_metric_utils.h"
#include "components/tabs/public/split_tab_data.h"
#include "components/tabs/public/split_tab_id.h"
#include "components/tabs/public/split_tab_visual_data.h"
#include "components/tabs/public/tab_group.h"
#include "components/tabs/public/tab_interface.h"
#include "components/web_modal/web_contents_modal_dialog_manager.h"
#include "components/zoom/zoom_controller.h"
#include "content/public/browser/color_chooser.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/file_select_listener.h"
#include "content/public/browser/invalidate_type.h"
#include "content/public/browser/keyboard_event_processing_result.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/site_instance.h"
#include "content/public/browser/ssl_status.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_exposed_isolation_level.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_features.h"
#include "content/public/common/page_zoom.h"
#include "content/public/common/profiling.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/webplugininfo.h"
#include "content/public/common/window_container_type.mojom-shared.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
#include "extensions/browser/process_manager.h"
#include "extensions/browser/process_map.h"
#include "extensions/buildflags/buildflags.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest_handlers/background_info.h"
#include "net/base/filename_util.h"
#include "third_party/blink/public/common/security/protocol_handler_security_level.h"
#include "third_party/blink/public/mojom/frame/blocked_navigation_types.mojom.h"
#include "third_party/blink/public/mojom/frame/fullscreen.mojom.h"
#include "third_party/blink/public/mojom/page/draggable_region.mojom.h"
#include "third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom.h"
#include "third_party/blink/public/mojom/window_features/window_features.mojom.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/mojom/window_show_state.mojom.h"
#include "ui/base/window_open_disposition.h"
#include "ui/gfx/font_list.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/text_elider.h"
#include "ui/gfx/text_utils.h"
#include "url/origin.h"
#include "url/scheme_host_port.h"

#if BUILDFLAG(IS_WIN)
// windows.h must be included before shellapi.h
#include <windows.h>

#include <shellapi.h>

#include "chrome/browser/ui/view_ids.h"
#include "ui/base/win/shell.h"
#endif  // BUILDFLAG(IS_WIN)

#if BUILDFLAG(IS_CHROMEOS)
#include "ash/constants/ash_features.h"
#include "chrome/browser/ash/guest_os/guest_os_terminal.h"
#include "chrome/browser/ui/settings_window_manager_chromeos.h"
#endif

#if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
#include "components/captive_portal/content/captive_portal_tab_helper.h"
#endif

#if BUILDFLAG(ENABLE_PRINTING)
#include "components/printing/browser/print_composite_client.h"
#endif

#if BUILDFLAG(ENABLE_PAINT_PREVIEW)
#include "components/paint_preview/browser/paint_preview_client.h"  // nogncheck
#endif

#if BUILDFLAG(IS_MAC)
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/display/types/display_constants.h"
#endif  // BUILDFLAG(IS_MAC)

#if !BUILDFLAG(IS_ANDROID)
#include "chrome/browser/preloading/preview/preview_manager.h"
#endif

#if BUILDFLAG(IS_OZONE)
#include "ui/ozone/public/platform_session_manager.h"
#endif

#if BUILDFLAG(ENABLE_GLIC)
#include "chrome/browser/ai/ai_data_keyed_service.h"          // nogncheck
#include "chrome/browser/ai/ai_data_keyed_service_factory.h"  // nogncheck
#include "chrome/browser/glic/public/glic_enabling.h"
#include "chrome/browser/glic/public/glic_keyed_service.h"
#endif

#if defined(USE_AURA)
#include "chrome/browser/ui/overscroll_pref_manager.h"
#endif  // defined(USE_AURA)

using base::UserMetricsAction;
using content::NavigationController;
using content::NavigationEntry;
using content::OpenURLParams;
using content::Referrer;
using content::RenderWidgetHostView;
using content::SiteInstance;
using content::WebContents;
using custom_handlers::ProtocolHandler;
using extensions::Extension;
using input::NativeWebKeyboardEvent;
using ui::WebDialogDelegate;
using web_modal::WebContentsModalDialogManager;

///////////////////////////////////////////////////////////////////////////////

namespace {

// How long we wait before updating the browser chrome while loading a page.
constexpr base::TimeDelta kUIUpdateCoalescingTime = base::Milliseconds(200);

const extensions::Extension* GetExtensionForOrigin(
    Profile* profile,
    const GURL& security_origin) {
#if BUILDFLAG(ENABLE_EXTENSIONS)
  if (!security_origin.SchemeIs(extensions::kExtensionScheme)) {
    return nullptr;
  }

  const extensions::Extension* extension =
      extensions::ExtensionRegistry::Get(profile)->enabled_extensions().GetByID(
          security_origin.GetHost());
  DCHECK(extension);
  return extension;
#else
  return nullptr;
#endif
}

// Returns a pair [last_window, last_window_for_profile] indicating if `browser`
// is the only browser in total and for this profile.
// Ignores browsers that are in the process of closing.
std::pair<bool, bool> IsLastWindow(const Browser& browser) {
  bool last_window = true;
  bool last_window_for_profile = true;
  for (Browser* other_browser : *BrowserList::GetInstance()) {
    // Don't count this browser window or any other in the process of closing.
    // Window closing may be delayed, and windows that are in the process of
    // closing don't count against our totals.
    if (other_browser == &browser ||
        other_browser->IsAttemptingToCloseBrowser()) {
      continue;
    }

    last_window = false;

    if (other_browser->profile() == browser.profile()) {
      last_window_for_profile = false;
      break;
    }
  }

  return {last_window, last_window_for_profile};
}

// Returns whether the cookie migration notice should be shown: the migration
// is not complete, and this is the last browser window open for this profile.
bool ShouldShowCookieMigrationNoticeForBrowser(const Browser& browser) {
  if (!CanShowCookieClearOnExitMigrationNotice(browser)) {
    return false;
  }

  auto [last_window, last_window_for_profile] = IsLastWindow(browser);
  return last_window_for_profile;
}

void UpdateTabGroupSessionMetadata(Browser* browser,
                                   const tab_groups::TabGroupId& group_id) {
  SessionService* const session_service =
      SessionServiceFactory::GetForProfile(browser->profile());
  if (!session_service) {
    return;
  }

  const tab_groups::TabGroupVisualData* visual_data =
      browser->tab_strip_model()
          ->group_model()
          ->GetTabGroup(group_id)
          ->visual_data();

  session_service->SetTabGroupMetadata(browser->session_id(), group_id,
                                       visual_data);
}

bool ShouldHideUIForFullscreenWrapper(const Browser* browser) {
  return browser->ShouldHideUIForFullscreen();
}

bool AlwaysReturnTrue(const Browser* browser) {
  return true;
}

bool AlwaysReturnFalse(const Browser* browser) {
  return false;
}

base::FunctionRef<bool(const Browser*)> MaybeLazyIsFullscreen(
    const Browser* browser) {
  // Returns a base::FunctionRef instead of a Base::RepeatingCallback to reduce
  // allocation overhead, since this is a performance experiment.
  if (base::FeatureList::IsEnabled(features::kInlineFullscreenPerfExperiment)) {
    // In the experiment branch, lazy-eval ShouldHideUIForFullscreen.
    return &ShouldHideUIForFullscreenWrapper;
  }

  // In the control branch, eagerly evaluate ShouldHideUIForFullscreen.
  return browser->ShouldHideUIForFullscreen() ? &AlwaysReturnTrue
                                              : &AlwaysReturnFalse;
}

bool HasActorTask(Profile* profile, content::RenderFrameHost* rfh) {
  auto* actor_service = actor::ActorKeyedService::Get(profile);
  if (!actor_service) {
    return false;
  }

  auto* wc = content::WebContents::FromRenderFrameHost(rfh);
  if (!wc) {
    return false;
  }

  const auto* tab_interface = tabs::TabInterface::MaybeGetFromContents(wc);
  if (!tab_interface) {
    return false;
  }

  return !actor_service->GetTaskFromTab(*tab_interface).is_null();
}

}  // namespace

////////////////////////////////////////////////////////////////////////////////
// Browser, CreateParams:

BrowserWindowInterface* BrowserWindowInterface::FromSessionID(
    const SessionID& session_id) {
  for (Browser* browser : *BrowserList::GetInstance()) {
    if (browser->GetSessionID() == session_id) {
      return browser;
    }
  }
  return nullptr;
}

Browser::CreateParams::CreateParams(Profile* profile, bool user_gesture)
    : CreateParams(TYPE_NORMAL, profile, user_gesture) {}

Browser::CreateParams::CreateParams(Type type,
                                    Profile* profile,
                                    bool user_gesture)
    : type(type), profile(profile), user_gesture(user_gesture) {}

Browser::CreateParams::CreateParams(const CreateParams& other) = default;

Browser::CreateParams& Browser::CreateParams::operator=(
    const CreateParams& other) = default;

Browser::CreateParams::~CreateParams() = default;

// static
Browser::CreateParams Browser::CreateParams::CreateForAppBase(
    bool is_popup,
    const std::string& app_name,
    bool trusted_source,
    const gfx::Rect& window_bounds,
    Profile* profile,
    bool user_gesture) {
  DCHECK(!app_name.empty());

  CreateParams params(is_popup ? Type::TYPE_APP_POPUP : Type::TYPE_APP, profile,
                      user_gesture);
  params.app_name = app_name;
  params.trusted_source = trusted_source;
  params.initial_bounds = window_bounds;

  return params;
}

// static
Browser::CreateParams Browser::CreateParams::CreateForApp(
    const std::string& app_name,
    bool trusted_source,
    const gfx::Rect& window_bounds,
    Profile* profile,
    bool user_gesture) {
  return CreateForAppBase(false, app_name, trusted_source, window_bounds,
                          profile, user_gesture);
}

// static
Browser::CreateParams Browser::CreateParams::CreateForAppPopup(
    const std::string& app_name,
    bool trusted_source,
    const gfx::Rect& window_bounds,
    Profile* profile,
    bool user_gesture) {
  return CreateForAppBase(true, app_name, trusted_source, window_bounds,
                          profile, user_gesture);
}

// static
Browser::CreateParams Browser::CreateParams::CreateForPictureInPicture(
    const std::string& app_name,
    bool trusted_source,
    Profile* profile,
    bool user_gesture) {
  Browser::CreateParams browser_params(Browser::TYPE_PICTURE_IN_PICTURE,
                                       profile, user_gesture);
  browser_params.app_name = app_name;
  browser_params.trusted_source = trusted_source;
  return browser_params;
}

// static
Browser::CreateParams Browser::CreateParams::CreateForDevTools(
    Profile* profile) {
  CreateParams params(TYPE_DEVTOOLS, profile, true);
  params.app_name = DevToolsWindow::kDevToolsApp;
  params.trusted_source = true;
  return params;
}

///////////////////////////////////////////////////////////////////////////////
// Browser, Constructors, Creation, Showing:

// static
BrowserWindowInterface::CreationStatus Browser::GetCreationStatusForProfile(
    Profile* profile) {
  return GetBrowserWindowCreationStatusForProfile(*profile);
}

// static
Browser* Browser::Create(const CreateParams& params) {
  // If this is failing, a caller is trying to create a browser when creation is
  // not possible, e.g. using the wrong profile or during shutdown. The caller
  // should handle this; see e.g. crbug.com/1141608 and crbug.com/1261628.
  CHECK_EQ(CreationStatus::kOk, GetCreationStatusForProfile(params.profile));

  std::unique_ptr<Browser> browser = base::WrapUnique(new Browser(params));
  Browser* const browser_ptr = browser.get();
  BrowserManagerServiceFactory::GetForProfile(params.profile)
      ->AddBrowser(std::move(browser));
  return browser_ptr;
}

// static
std::unique_ptr<Browser> Browser::DeprecatedCreateOwnedForTesting(
    const CreateParams& params) {
  CHECK_IS_TEST();
  // If this is failing, a caller is trying to create a browser when creation is
  // not possible, e.g. using the wrong profile or during shutdown. The caller
  // should handle this; see e.g. crbug.com/1141608 and crbug.com/1261628.
  CHECK_EQ(CreationStatus::kOk, GetCreationStatusForProfile(params.profile));
  return base::WrapUnique(new Browser(params));
}

Browser::Browser(const CreateParams& params)
    : create_params_(params),
      type_(params.type),
      profile_(params.profile),
      window_(nullptr),
      tab_strip_model_delegate_(
          std::make_unique<chrome::BrowserTabStripModelDelegate>(this)),
      tab_strip_model_(std::make_unique<TabStripModel>(
          tab_strip_model_delegate_.get(),
          params.profile,
          // Tab groups are disabled for app browsers.
          (type_ == TYPE_APP || type_ == TYPE_APP_POPUP)
              ? nullptr
              : TabGroupModelFactory::GetInstance())),
      app_name_(params.app_name),
      is_trusted_source_(params.trusted_source),
      session_id_(SessionID::NewUnique()),
      omit_from_session_restore_(params.omit_from_session_restore),
      should_trigger_session_restore_(params.should_trigger_session_restore),
      cancel_download_confirmation_state_(
          CancelDownloadConfirmationState::kNotPrompted),
      override_bounds_(params.initial_bounds),
      initial_show_state_(params.initial_show_state),
      initial_workspace_(params.initial_workspace),
      initial_visible_on_all_workspaces_state_(
          params.initial_visible_on_all_workspaces_state),
      creation_source_(params.creation_source),
      unload_controller_(this),
      window_has_shown_(false),
      user_title_(params.user_title) {
  if (!profile_->IsOffTheRecord()) {
    profile_keep_alive_ = std::make_unique<ScopedProfileKeepAlive>(
        params.profile->GetOriginalProfile(),
        ProfileKeepAliveOrigin::kBrowserWindow);
  }

  tab_strip_model_->AddObserver(this);

  ThemeServiceFactory::GetForProfile(profile_)->AddObserver(this);

  profile_pref_registrar_.Init(profile_->GetPrefs());
  profile_pref_registrar_.Add(
      prefs::kDevToolsAvailability,
      base::BindRepeating(&Browser::OnDevToolsAvailabilityChanged,
                          base::Unretained(this)));

  ProfileMetrics::LogProfileLaunch(profile_);

  if (params.skip_window_init_for_testing) {
    // This is as initialized as the window will ever get.
    is_initialized_ = true;
    return;
  }

  // BrowserWindowFeatures need to be initialized before browser window
  // creation, so that the features can be used in creating components
  // in browser window.
  features_ = std::make_unique<BrowserWindowFeatures>();
  features_->Init(this);

  SessionServiceBase* session_service =
      GetAppropriateSessionServiceForSessionRestore(this);
#if BUILDFLAG(IS_OZONE)
  if (session_service && session_service->GetPlatformSessionId()) {
    platform_session_data_ = ui::PlatformSessionWindowData{
        .session_id = session_service->GetPlatformSessionId().value(),
        .window_id = session_id_.id(),
        .restore_id = params.restore_id > Browser::kDefaultRestoreId
                          ? std::optional<int32_t>(params.restore_id)
                          : std::nullopt};
  }
#endif  // BUILDFLAG(IS_OZONE)

  if (params.window) {
    CHECK_IS_TEST() << "Browser::CreateParams::window is a test-only param";
  }
  window_ =
      params.window
          ? std::unique_ptr<BrowserWindow, BrowserWindowDeleter>(params.window)
          : BrowserWindow::CreateBrowserWindow(this, params.user_gesture,
                                               params.in_tab_dragging);

  if (auto* const app_browser_controller = GetAppBrowserController();
      app_browser_controller) {
    app_browser_controller->UpdateCustomTabBarVisibility(false);
  }

  if (session_service) {
    session_service->WindowOpened(this);
  }

  // Initialize the browser features that rely on the browser window now that it
  // is initialized.
  features_->InitPostWindowConstruction(this);

  // All initialization is complete; after this point, the browser should be on
  // the browser list until it is marked for destruction.
  is_initialized_ = true;

  BrowserList::AddBrowser(this);
}

Browser::~Browser() {
  if (!is_delete_scheduled_) {
    // Guarantee the Browser has performed the necessary cleanup in the
    // `OnWindowClosing()` lifecycle hook. This may not be invoked during
    // Browser shutdown specifically in cases where clients directly reset
    // the Browser unique_ptr.
    force_skip_warning_user_on_close_ = true;
    OnWindowClosing();
  }

  BrowserList::RemoveBrowser(this);
  window_.reset();

  // Tear down `BrowserWindowFeatures` to avoid exposing it to Browser in a
  // partially-destroyed state.
  features_.reset();

  // Stop observing notifications and destroy the tab monitor before continuing
  // with destruction. Profile destruction will unload extensions and reentrant
  // calls to Browser:: should be avoided while it is being torn down.
  ThemeServiceFactory::GetForProfile(profile_)->RemoveObserver(this);

  // The tab strip should not have any tabs at this point.
  //
  // TODO(crbug.com/40887606): This DCHECK doesn't always pass.
  // TODO(crbug.com/40064092): convert this to CHECK.
  DCHECK(tab_strip_model_->empty());

  // If closing the window is going to trigger a shutdown, then we need to
  // schedule all active downloads to be cancelled. This needs to be after
  // removing |this| from BrowserList so that OkToClose...() can determine
  // whether there are any other windows open for the browser.
  int num_downloads;
  if (!browser_defaults::kBrowserAliveWithNoWindows &&
      OkToCloseWithInProgressDownloads(&num_downloads) ==
          DownloadCloseType::kBrowserShutdown) {
    DownloadCoreService::CancelAllDownloads(
        DownloadCoreService::CancelDownloadsTrigger::kShutdown);
  }

  SessionServiceBase* service = GetAppropriateSessionServiceForProfile(this);

  if (service) {
    service->WindowClosed(session_id_);
  }

  profile_pref_registrar_.Reset();

  // The system incognito profile should not try be destroyed using
  // ProfileDestroyer::DestroyProfileWhenAppropriate(). This profile can be
  // used, at least, by the user manager window. This window is not a browser,
  // therefore, BrowserList::IsOffTheRecordBrowserActiveForProfile(profile_)
  // returns false, while the user manager window is still opened.
  // This cannot be fixed in ProfileDestroyer::DestroyProfileWhenAppropriate(),
  // because the ProfileManager needs to be able to destroy all profiles when
  // it is destroyed. See crbug.com/527035
  //
  // Non-primary OffTheRecord profiles should not be destroyed directly by
  // Browser (e.g. for offscreen tabs, https://crbug.com/664351).
  //
  // TODO(crbug.com/40159237): Use ScopedProfileKeepAlive for Incognito too,
  // instead of separate logic for Incognito and regular profiles.
  if (profile_->IsIncognitoProfile() &&
      !BrowserList::IsOffTheRecordBrowserInUse(profile_) &&
      !profile_->IsSystemProfile()) {
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
    // The Printing Background Manager holds onto preview dialog WebContents
    // whose corresponding print jobs have not yet fully spooled. Make sure
    // these get destroyed before tearing down the incognito profile so that
    // their RenderFrameHosts can exit in time - see crbug.com/579155
    g_browser_process->background_printing_manager()
        ->DeletePreviewContentsForBrowserContext(profile_);
#endif
    // An incognito profile is no longer needed, this indirectly frees
    // its cache and cookies once it gets destroyed at the appropriate time.
    ProfileDestroyer::DestroyOTRProfileWhenAppropriate(profile_);
  }
}

///////////////////////////////////////////////////////////////////////////////
// Getters & Setters

BrowserView& Browser::GetBrowserView() {
  return CHECK_DEREF(window_->AsBrowserView());
}

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

base::WeakPtr<const Browser> Browser::AsWeakPtr() const {
  return weak_factory_.GetWeakPtr();
}

///////////////////////////////////////////////////////////////////////////////
// Browser, State Storage and Retrieval for UI:

GURL Browser::GetNewTabURL() const {
  if (auto* const app_browser_controller = GetAppBrowserController();
      app_browser_controller) {
    return app_browser_controller->GetAppNewTabUrl();
  }
  return GURL(chrome::kChromeUINewTabURL);
}

gfx::Image Browser::GetCurrentPageIcon() const {
  WebContents* web_contents = tab_strip_model_->GetActiveWebContents();
  // |web_contents| can be NULL since GetCurrentPageIcon() is called by the
  // window during the window's creation (before tabs have been added).
  favicon::FaviconDriver* favicon_driver =
      web_contents
          ? favicon::ContentFaviconDriver::FromWebContents(web_contents)
          : nullptr;
  return favicon_driver ? favicon_driver->GetFavicon() : gfx::Image();
}

std::u16string Browser::GetWindowTitleForCurrentTab(
    bool include_app_name) const {
  if (!user_title_.empty()) {
    return base::UTF8ToUTF16(user_title_);
  }

  // For document picture-in-picture windows, we use the title from the opener
  // WebContents instead of the picture-in-picture WebContents itself.
  content::WebContents* web_contents_for_title =
      is_type_picture_in_picture()
          ? PictureInPictureWindowManager::GetInstance()->GetWebContents()
          : tab_strip_model_->GetActiveWebContents();

  return GetWindowTitleFromWebContents(include_app_name,
                                       web_contents_for_title);
}

std::u16string Browser::GetWindowTitleForTab(int index) const {
  std::u16string title = base::UTF8ToUTF16(user_title_);

  if (title.empty()) {
    title = tab_strip_model_->GetWebContentsAt(index)->GetTitle();
    if (is_type_picture_in_picture()) {
      content::WebContents* pip_web_contents =
          PictureInPictureWindowManager::GetInstance()->GetWebContents();
      if (pip_web_contents) {
        title = pip_web_contents->GetTitle();
      }
    }
    title = FormatTitleForDisplay(title);
  }

  if (title.empty() && (is_type_normal() || is_type_popup())) {
    title = CoreTabHelper::GetDefaultTitle();
  }

  return title;
}

std::u16string Browser::GetTitleForTab(int index) const {
  std::u16string title = FormatTitleForDisplay(
      tab_strip_model_->GetWebContentsAt(index)->GetTitle());

  if (title.empty()) {
    title = CoreTabHelper::GetDefaultTitle();
  }

  return title;
}

std::u16string Browser::GetWindowTitleForMaxWidth(int max_width) const {
  static constexpr unsigned int kMinTitleCharacters = 4;
  const gfx::FontList font_list;

  if (!user_title_.empty()) {
    std::u16string title = base::UTF8ToUTF16(user_title_);
    std::u16string pixel_elided_title = gfx::ElideText(
        title, font_list, max_width, gfx::ElideBehavior::ELIDE_TAIL);
    std::u16string character_elided_title =
        gfx::TruncateString(title, kMinTitleCharacters, gfx::CHARACTER_BREAK);
    return pixel_elided_title.size() > character_elided_title.size()
               ? pixel_elided_title
               : character_elided_title;
  }

  const auto num_more_tabs = tab_strip_model_->count() - 1;
  const std::u16string format_string = l10n_util::GetPluralStringFUTF16(
      IDS_BROWSER_WINDOW_TITLE_MENU_ENTRY, num_more_tabs);

  // First, format with an empty string to see how much space we have available.
  std::u16string temp_window_title =
      base::ReplaceStringPlaceholders(format_string, std::u16string(), nullptr);
  int width = max_width - GetStringWidth(temp_window_title, font_list);

  std::u16string title;
  content::WebContents* contents = tab_strip_model_->GetActiveWebContents();
  // |contents| can be NULL if GetWindowTitleForMenu is called during the
  // window's creation (before tabs have been added).
  if (contents) {
    auto* const app_browser_controller = GetAppBrowserController();
    title = FormatTitleForDisplay(app_browser_controller
                                      ? app_browser_controller->GetTitle()
                                      : contents->GetTitle());
  }

  // If there is no title, leave it empty for apps.
  if (title.empty() && (is_type_normal() || is_type_popup())) {
    title = CoreTabHelper::GetDefaultTitle();
  }

  // Try to elide the title to fit the pixel width. If that will make the title
  // shorter than the minimum character limit, use a character elided title
  // instead.
  std::u16string pixel_elided_title =
      gfx::ElideText(title, font_list, width, gfx::ElideBehavior::ELIDE_TAIL);
  std::u16string character_elided_title =
      gfx::TruncateString(title, kMinTitleCharacters, gfx::CHARACTER_BREAK);
  title = pixel_elided_title.size() > character_elided_title.size()
              ? pixel_elided_title
              : character_elided_title;

  // Finally, add the page title.
  return base::ReplaceStringPlaceholders(format_string, title, nullptr);
}

std::u16string Browser::GetWindowTitleFromWebContents(
    bool include_app_name,
    content::WebContents* contents) const {
  std::u16string title = base::UTF8ToUTF16(user_title_);

  // |contents| can be NULL because GetWindowTitleForCurrentTab is called by the
  // window during the window's creation (before tabs have been added).
  if (title.empty() && contents) {
    auto* const app_browser_controller = GetAppBrowserController();
    title = FormatTitleForDisplay(app_browser_controller
                                      ? app_browser_controller->GetTitle()
                                      : contents->GetTitle());
#if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
    // If the app name is requested and this is a captive portal window, the
    // title should indicate that this is a captive portal window. Captive
    // portal windows should always be pop-ups, and the is_captive_portal_window
    // condition should not change over the lifetime of a WebContents.
    if (include_app_name &&
        captive_portal::CaptivePortalTabHelper::FromWebContents(contents) &&
        captive_portal::CaptivePortalTabHelper::FromWebContents(contents)
            ->is_captive_portal_window()) {
      DCHECK(is_type_popup());
      return l10n_util::GetStringFUTF16(
          IDS_CAPTIVE_PORTAL_BROWSER_WINDOW_TITLE_FORMAT,
          title.empty() ? CoreTabHelper::GetDefaultTitle() : title);
    }
#endif
  }

  // If there is no title, leave it empty for apps.
  if (title.empty() && (is_type_normal() || is_type_popup())) {
    title = CoreTabHelper::GetDefaultTitle();
  }

#if BUILDFLAG(IS_MAC)
  // On Mac, we don't want to suffix the page title with the application name.
  return title;
#else
  // If there is no title and this is an app, fall back on the app name. This
  // ensures that the native window gets a title which is important for a11y,
  // for example the window selector uses the Aura window title.
  if (title.empty() &&
      (is_type_app() || is_type_app_popup() || is_type_devtools()) &&
      include_app_name) {
    auto* const app_browser_controller = GetAppBrowserController();
    return app_browser_controller ? app_browser_controller->GetAppShortName()
                                  : base::UTF8ToUTF16(app_name());
  }
  // Include the app name in window titles for tabbed browser windows when
  // requested with |include_app_name|.
  return ((is_type_normal() || is_type_popup()) && include_app_name)
             ? l10n_util::GetStringFUTF16(IDS_BROWSER_WINDOW_TITLE_FORMAT,
                                          title)
             : title;
#endif  // BUILDFLAG(IS_MAC)
}

// static
std::u16string Browser::FormatTitleForDisplay(std::u16string title) {
  size_t current_index = 0;
  size_t match_index;
  while ((match_index = title.find(L'\n', current_index)) !=
         std::u16string::npos) {
    title.replace(match_index, 1, std::u16string());
    current_index = match_index;
  }

  return title;
}

///////////////////////////////////////////////////////////////////////////////
// Browser, OnBeforeUnload handling:

Browser::WarnBeforeClosingResult Browser::MaybeWarnBeforeClosing(
    Browser::WarnBeforeClosingCallback warn_callback) {
  // If the browser can close right away (we've indicated that we want to skip
  // before-unload handlers by setting `force_skip_warning_user_on_close_` to
  // true or there are no pending downloads we need to prompt about) then
  // there's no need to warn.
  if (force_skip_warning_user_on_close_) {
    return WarnBeforeClosingResult::kOkToClose;
  }

  // `CanCloseWithInProgressDownloads()` may trigger a modal dialog.
  bool can_close_with_downloads = CanCloseWithInProgressDownloads();
  if (can_close_with_downloads &&
      !ShouldShowCookieMigrationNoticeForBrowser(*this)) {
    return WarnBeforeClosingResult::kOkToClose;
  }

  // If there is no download warning, show the cookie migration notice now.
  // Otherwise, the download warning is being shown. Cookie migration notice
  // will be shown after, if needed.
  if (can_close_with_downloads) {
    ShowCookieClearOnExitMigrationNotice(
        *this, base::BindOnce(&Browser::CookieMigrationNoticeResponse,
                              weak_factory_.GetWeakPtr()));
  }

  DCHECK(!warn_before_closing_callback_)
      << "Tried to close window during close warning; dialog should be modal.";
  warn_before_closing_callback_ = std::move(warn_callback);

  return WarnBeforeClosingResult::kDoNotClose;
}

bool Browser::HandleBeforeClose() {
  const auto get_closing_status =
      [this]() -> BrowserWindowInterface::ClosingStatus {
    // If `force_skip_warning_user_` is true, then we should immediately
    // return true.
    if (force_skip_warning_user_on_close_) {
      return BrowserWindowInterface::ClosingStatus::kPermitted;
    }

    // If the user needs to see one or more warnings, hold off closing the
    // browser.
    const WarnBeforeClosingResult result =
        MaybeWarnBeforeClosing(base::BindOnce(&Browser::FinishWarnBeforeClosing,
                                              weak_factory_.GetWeakPtr()));
    if (result == WarnBeforeClosingResult::kDoNotClose) {
      return BrowserWindowInterface::ClosingStatus::kDeniedByUser;
    }

    return unload_controller_.GetBrowserClosingStatus();
  };

  // Notify clients if close was cancelled.
  const BrowserWindowInterface::ClosingStatus close_status =
      get_closing_status();
  const bool close_permitted =
      close_status == BrowserWindowInterface::ClosingStatus::kPermitted;
  if (!close_permitted) {
    browser_close_cancelled_callback_list_.Notify(this, close_status);
  }
  return close_permitted;
}

bool Browser::TryToCloseWindow(
    bool skip_beforeunload,
    const base::RepeatingCallback<void(bool)>& on_close_confirmed) {
  cancel_download_confirmation_state_ =
      CancelDownloadConfirmationState::kResponseReceived;
  return unload_controller_.TryToCloseWindow(skip_beforeunload,
                                             on_close_confirmed);
}

void Browser::ResetTryToCloseWindow() {
  cancel_download_confirmation_state_ =
      CancelDownloadConfirmationState::kNotPrompted;
  unload_controller_.ResetTryToCloseWindow();
}

bool Browser::IsAttemptingToCloseBrowser() const {
  return unload_controller_.is_attempting_to_close_browser();
}

bool Browser::ShouldRunUnloadListenerBeforeClosing(
    content::WebContents* web_contents) {
  return !force_skip_warning_user_on_close_ &&
         unload_controller_.ShouldRunUnloadEventsHelper(web_contents);
}

bool Browser::RunUnloadListenerBeforeClosing(
    content::WebContents* web_contents) {
  return !force_skip_warning_user_on_close_ &&
         unload_controller_.RunUnloadEventsHelper(web_contents);
}

void Browser::SetWindowUserTitle(const std::string& user_title) {
  user_title_ = user_title;
  window_->UpdateTitleBar();
  // See comment in Browser::OnTabGroupChanged
  DCHECK(!IsRelevantToAppSessionService(type_));
  SessionService* const session_service =
      SessionServiceFactory::GetForProfile(profile_);
  if (session_service) {
    session_service->SetWindowUserTitle(session_id(), user_title);
  }
}

Browser* Browser::GetBrowserForOpeningWebUi() {
  if (!is_type_picture_in_picture()) {
    return this;
  }

  if (!opener_browser_) {
    auto* opener_web_contents =
        PictureInPictureWindowManager::GetInstance()->GetWebContents();
    // We should always have an opener web contents if the current browser is a
    // picture-in-picture type.
    DCHECK(opener_web_contents);
    opener_browser_ = chrome::FindBrowserWithTab(opener_web_contents);
  }

  return opener_browser_;
}

std::vector<StatusBubble*> Browser::GetStatusBubblesForTesting() {
  return GetStatusBubbles();
}

Profile* Browser::GetProfile() {
  return profile();
}

const Profile* Browser::GetProfile() const {
  return profile();
}

void Browser::OpenGURL(const GURL& gurl, WindowOpenDisposition disposition) {
  OpenURL(content::OpenURLParams(gurl, content::Referrer(), disposition,
                                 ui::PAGE_TRANSITION_LINK,
                                 /*is_renderer_initiated=*/false),
          /*navigation_handle_callback=*/{});
}

const SessionID& Browser::GetSessionID() const {
  return session_id_;
}

TabStripModel* Browser::GetTabStripModel() {
  return tab_strip_model_.get();
}

const TabStripModel* Browser::GetTabStripModel() const {
  return tab_strip_model_.get();
}

bool Browser::IsTabStripVisible() {
  return window_ && window_->IsToolbarShowing();
}

bool Browser::ShouldHideUIForFullscreen() const {
  // Windows and GTK remove the browser controls in fullscreen, but Mac and Ash
  // keep the controls in a slide-down panel.
  return window_ && window_->ShouldHideUIForFullscreen();
}

base::CallbackListSubscription Browser::RegisterBrowserDidClose(
    BrowserDidCloseCallback callback) {
  return browser_did_close_callback_list_.Add(std::move(callback));
}

base::CallbackListSubscription Browser::RegisterBrowserCloseCancelled(
    BrowserCloseCancelledCallback callback) {
  return browser_close_cancelled_callback_list_.Add(std::move(callback));
}

base::WeakPtr<BrowserWindowInterface> Browser::GetWeakPtr() {
  return AsWeakPtr();
}

base::CallbackListSubscription Browser::RegisterActiveTabDidChange(
    ActiveTabChangeCallback callback) {
  return did_active_tab_change_callback_list_.Add(std::move(callback));
}

tabs::TabInterface* Browser::GetActiveTabInterface() {
  return tab_strip_model_->GetActiveTab();
}

BrowserWindowFeatures& Browser::GetFeatures() {
  return *features_.get();
}

const BrowserWindowFeatures& Browser::GetFeatures() const {
  return *features_.get();
}

ui::UnownedUserDataHost& Browser::GetUnownedUserDataHost() {
  return unowned_user_data_host_;
}

const ui::UnownedUserDataHost& Browser::GetUnownedUserDataHost() const {
  return unowned_user_data_host_;
}

web_modal::WebContentsModalDialogHost*
Browser::GetWebContentsModalDialogHostForWindow() {
  return window_->GetWebContentsModalDialogHost();
}

web_modal::WebContentsModalDialogHost*
Browser::GetWebContentsModalDialogHostForTab(
    tabs::TabInterface* tab_interface) {
  return GetWebContentsModalDialogHost(tab_interface->GetContents());
}

bool Browser::IsActive() const {
// TODO(https://crbug.com/376306245): This is a temporary workaround for the
// fact that window_->IsActive() does not return the right result for macOS
// standalone PWA windows. This new behavior is still not technically correct,
// since it's checking that the last active window is `this`, as opposed to
// whether `this` is active.
#if BUILDFLAG(IS_MAC)
  // If this is a standalone PWA window, check BrowserList instead.
  if (GetAppBrowserController()) {
    return GetLastActiveBrowserWindowInterfaceWithAnyProfile() == this;
  }
#endif
  return is_active_;
}

base::CallbackListSubscription Browser::RegisterDidBecomeActive(
    DidBecomeActiveCallback callback) {
  return did_become_active_callback_list_.Add(std::move(callback));
}

base::CallbackListSubscription Browser::RegisterDidBecomeInactive(
    DidBecomeInactiveCallback callback) {
  return did_become_inactive_callback_list_.Add(std::move(callback));
}

void Browser::SynchronouslyDestroyBrowser() {
  // TODO(crbug.com/413168662): Eliminate the need for BrowserCloseManager to
  // call this directly, instead allow Browsers to be destroyed by their owning
  // BrowserManagerService at shutdown.
  BrowserManagerServiceFactory::GetForProfile(profile())->DeleteBrowser(this);
  // `this` is no longer valid from this point forward.
}

ExclusiveAccessManager* Browser::GetExclusiveAccessManager() {
  return GetFeatures().exclusive_access_manager();
}

BrowserActions* Browser::GetActions() {
  return GetFeatures().browser_actions();
}

BrowserWindowInterface::Type Browser::GetType() const {
  return type_;
}

web_app::AppBrowserController* Browser::GetAppBrowserController() {
  return GetFeatures().app_browser_controller();
}

const web_app::AppBrowserController* Browser::GetAppBrowserController() const {
  return GetFeatures().app_browser_controller();
}

std::vector<tabs::TabInterface*> Browser::GetAllTabInterfaces() {
  std::vector<tabs::TabInterface*> results;
  for (int index = 0; index < tab_strip_model_->count(); ++index) {
    results.push_back(tab_strip_model_->GetTabAtIndex(index));
  }
  return results;
}

Browser* Browser::GetBrowserForMigrationOnly() {
  return this;
}

const Browser* Browser::GetBrowserForMigrationOnly() const {
  return this;
}

bool Browser::IsTabModalPopupDeprecated() const {
  return is_tab_modal_popup_deprecated_;
}

bool Browser::CanShowCallToAction() const {
  return !showing_call_to_action_;
}

std::unique_ptr<ScopedWindowCallToAction> Browser::ShowCallToAction() {
  return std::make_unique<ScopedWindowCallToActionImpl>(this);
}

ui::BaseWindow* Browser::GetWindow() {
  return window_.get();
}

const ui::BaseWindow* Browser::GetWindow() const {
  return window_.get();
}

DesktopBrowserWindowCapabilities* Browser::capabilities() {
  return DesktopBrowserWindowCapabilities::From(this);
}

const DesktopBrowserWindowCapabilities* Browser::capabilities() const {
  return DesktopBrowserWindowCapabilities::From(this);
}

void Browser::DidBecomeActive() {
  if (!is_active_) {
    is_active_ = true;
    BrowserList::SetLastActive(this);
    did_become_active_callback_list_.Notify(this);
  }
}

void Browser::DidBecomeInactive() {
  if (is_active_) {
    is_active_ = false;
    BrowserList::NotifyBrowserNoLongerActive(this);
    did_become_inactive_callback_list_.Notify(this);
  }
}

#if BUILDFLAG(IS_CHROMEOS)
bool Browser::IsLockedForOnTask() {
  return on_task_locked_;
}

void Browser::SetLockedForOnTask(bool locked) {
  on_task_locked_ = locked;
  GetBrowserView().OnLockedForOnTaskUpdated();
}
#endif

void Browser::OnWindowClosing() {
  // There may be situations where async tasks, such as
  // UnloadController::ProcessPendingTabs, may call into OnWindowClosing() after
  // deletion has already been scheduled and closed notifications have been
  // propagated. No-op in such cases to avoid duplicating browser-closed
  // handling.
  if (is_delete_scheduled_) {
    return;
  }

  if (!HandleBeforeClose()) {
    return;
  }

  // Don't use GetForProfileIfExisting here, we want to force creation of the
  // session service so that user can restore what was open.
  SessionServiceBase* service = GetAppropriateSessionServiceForProfile(this);

  if (service) {
    service->WindowClosing(session_id());
  }

  sessions::TabRestoreService* tab_restore_service =
      TabRestoreServiceFactory::GetForProfile(profile());

  bool notify_restore_service = is_type_normal() && tab_strip_model_->count();
#if defined(USE_AURA) || BUILDFLAG(IS_MAC)
  notify_restore_service |= is_type_app() || is_type_app_popup();
#endif

  if (tab_restore_service && notify_restore_service) {
    tab_restore_service->BrowserClosing(GetFeatures().live_tab_context());
  }

  BrowserList::NotifyBrowserCloseStarted(this);

  if (!tab_strip_model_->empty()) {
    // Closing all the tabs results in eventually calling back to
    // OnWindowClosing() again.
    tab_strip_model_->CloseAllTabs();
  } else {
    // If there are no tabs, then a task will be scheduled (by views) to delete
    // this Browser.
    is_delete_scheduled_ = true;

    // Application should shutdown on last window close if the user is
    // explicitly trying to quit, or if there is nothing keeping the browser
    // alive (such as AppController on the Mac, or BackgroundContentsService for
    // background pages).
    const bool should_quit_if_last_browser =
        browser_shutdown::IsTryingToQuit() ||
        KeepAliveRegistry::GetInstance()->IsKeepingAliveOnlyByBrowserOrigin();

    // Below will not consider browsers for which delete has already been
    // scheduled.
    const bool is_last_browser =
        !GetLastActiveBrowserWindowInterfaceWithAnyProfile();

    if (should_quit_if_last_browser && is_last_browser) {
      browser_shutdown::OnShutdownStarting(
          browser_shutdown::ShutdownType::kWindowClose);
    }

    // At this point the browser has successfully closed and is scheduled for
    // deletion.
    browser_did_close_callback_list_.Notify(this);

    // Once a Browser has successfully closed, client code expects control to
    // return to the run loop before the instance is finally deleted. To
    // maintain existing expectations schedule the delete asynchronously here.
    // TODO(crbug.com/413168662): Explore synchronously destroying the browser
    // instead.
    base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
        FROM_HERE, base::BindOnce(&Browser::SynchronouslyDestroyBrowser,
                                  weak_factory_.GetWeakPtr()));
  }
}

////////////////////////////////////////////////////////////////////////////////
// In-progress download termination handling:

Browser::DownloadCloseType Browser::OkToCloseWithInProgressDownloads(
    int* num_downloads_blocking) const {
  DCHECK(num_downloads_blocking);
  *num_downloads_blocking = 0;

  // If we're not running a full browser process with a profile manager
  // (testing), it's ok to close the browser.
  if (!g_browser_process->profile_manager()) {
    return DownloadCloseType::kOk;
  }

  int total_download_count =
      DownloadCoreService::BlockingShutdownCountAllProfiles();
  if (total_download_count == 0) {
    return DownloadCloseType::kOk;  // No downloads; can definitely close.
  }

  // Figure out how many windows are open total, and associated with this
  // profile, that are relevant for the ok-to-close decision.
  auto [last_window, last_window_for_profile] = IsLastWindow(*this);

  // If there aren't any other windows, we're at browser shutdown,
  // which would cancel all current downloads.
  if (last_window) {
    *num_downloads_blocking = total_download_count;
    return DownloadCloseType::kBrowserShutdown;
  }

  // If there aren't any other windows on our profile, and we're an Incognito
  // or Guest profile, and there are downloads associated with that profile,
  // those downloads would be cancelled by our window (-> profile) close.
  DownloadCoreService* download_core_service =
      DownloadCoreServiceFactory::GetForBrowserContext(profile());
  if (last_window_for_profile &&
      (download_core_service->BlockingShutdownCount() > 0) &&
      (profile()->IsIncognitoProfile() || profile()->IsGuestSession())) {
    *num_downloads_blocking = download_core_service->BlockingShutdownCount();
    return profile()->IsGuestSession()
               ? DownloadCloseType::kLastWindowInGuestSession
               : DownloadCloseType::kLastWindowInIncognitoProfile;
  }

  // Those are the only conditions under which we will block shutdown.
  return DownloadCloseType::kOk;
}

////////////////////////////////////////////////////////////////////////////////
// Browser, Tab adding/showing functions:

void Browser::WindowFullscreenStateChanged() {
  browser_window_features()
      ->exclusive_access_manager()
      ->fullscreen_controller()
      ->WindowFullscreenStateChanged();
  GetCommandController()->FullscreenStateChanged();
  BookmarkBarController::From(this)->UpdateBookmarkBarState(
      BookmarkBarController::StateChangeReason::kToggleFullscreen);
}

void Browser::FullscreenTopUIStateChanged() {
  GetCommandController()->FullscreenStateChanged();
  BookmarkBarController::From(this)->UpdateBookmarkBarState(
      BookmarkBarController::StateChangeReason::kToolbarOptionChange);
}

void Browser::OnFindBarVisibilityChanged() {
  if (!IsPageActionMigrated(PageActionIconType::kFind)) {
    window()->UpdatePageActionIcon(PageActionIconType::kFind);
  } else {
    GetFeatures().GetFindBarController()->UpdatePageAction();
  }

  GetCommandController()->FindBarVisibilityChanged();
}

///////////////////////////////////////////////////////////////////////////////
// Browser, Assorted browser commands:

void Browser::ToggleFullscreenModeWithExtension(const GURL& extension_url) {
  browser_window_features()
      ->exclusive_access_manager()
      ->fullscreen_controller()
      ->ToggleBrowserFullscreenModeWithExtension(extension_url);
}

bool Browser::SupportsWindowFeature(WindowFeature feature) const {
  bool supports =
      SupportsWindowFeatureImpl(feature, /*check_can_support=*/false);
  // Supported features imply CanSupportWindowFeature.
  DCHECK(!supports || CanSupportWindowFeature(feature));
  return supports;
}

bool Browser::CanSupportWindowFeature(WindowFeature feature) const {
  return SupportsWindowFeatureImpl(feature, /*check_can_support=*/true);
}

void Browser::OpenFile() {
  GetFeatures().browser_select_file_dialog_controller()->OpenFile(
      tab_strip_model_->GetActiveWebContents(), window_->GetNativeWindow(),
      base::BindOnce(&Browser::OnFileSelectedFromDialog, AsWeakPtr()));
}

bool Browser::CanSaveContents(content::WebContents* web_contents) const {
  return chrome::CanSavePage(this);
}

bool Browser::ShouldDisplayFavicon(content::WebContents* web_contents) const {
  // Remove for all other tabbed web apps.
  if (auto* const app_browser_controller = GetAppBrowserController();
      app_browser_controller && app_browser_controller->has_tab_strip()) {
    return false;
  }

  // Otherwise, always display the favicon.
  return true;
}

///////////////////////////////////////////////////////////////////////////////

void Browser::UpdateUIForNavigationInTab(WebContents* contents,
                                         ui::PageTransition transition,
                                         NavigateParams::WindowAction action,
                                         bool user_initiated) {
  tab_strip_model_->TabNavigating(contents, transition);

  bool contents_is_selected =
      contents == tab_strip_model_->GetActiveWebContents();
  if (user_initiated && contents_is_selected && window()->GetLocationBar()) {
    // Forcibly reset the location bar if the url is going to change in the
    // current tab, since otherwise it won't discard any ongoing user edits,
    // since it doesn't realize this is a user-initiated action.
    window()->GetLocationBar()->Revert();
  }

  std::vector<StatusBubble*> status_bubbles = GetStatusBubbles();
  for (StatusBubble* status_bubble : status_bubbles) {
    status_bubble->Hide();
  }

  // Update the location bar. This is synchronous. We specifically don't
  // update the load state since the load hasn't started yet and updating it
  // will put it out of sync with the actual state like whether we're
  // displaying a favicon, which controls the throbber. If we updated it here,
  // the throbber will show the default favicon for a split second when
  // navigating away from the new tab page.
  ScheduleUIUpdate(contents, content::INVALIDATE_TYPE_URL);

  // Navigating contents can take focus (potentially taking it away from other,
  // currently-focused UI element like the omnibox) if the navigation was
  // initiated by the user (e.g., via omnibox, bookmarks, etc.).
  //
  // Note that focusing contents of NTP-initiated navigations is taken care of
  // elsewhere - see FocusTabAfterNavigationHelper.
  if (user_initiated && contents_is_selected &&
      (window()->IsActive() ||
       action == NavigateParams::WindowAction::kShowWindow)) {
    contents->SetInitialFocus();
  }
}

void Browser::RegisterKeepAlive() {
  keep_alive_ = std::make_unique<ScopedKeepAlive>(
      KeepAliveOrigin::BROWSER, KeepAliveRestartOption::DISABLED);
}
void Browser::UnregisterKeepAlive() {
  keep_alive_.reset();
}

///////////////////////////////////////////////////////////////////////////////
// Browser, PageNavigator implementation:

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

  return OpenURLFromTab(nullptr, params, std::move(navigation_handle_callback));
}

///////////////////////////////////////////////////////////////////////////////
// Browser, TabStripModelObserver implementation:

void Browser::OnTabStripModelChanged(TabStripModel* tab_strip_model,
                                     const TabStripModelChange& change,
                                     const TabStripSelectionChange& selection) {
  TRACE_EVENT2("ui", "Browser::OnTabStripModelChanged", "tab_strip_model",
               tab_strip_model, "change", change);
  switch (change.type()) {
    case TabStripModelChange::kInserted: {
      // Initialize find bar controller when tab having active find session
      // is inserted in a new window.
      find_in_page::FindTabHelper* find_tab_helper =
          find_in_page::FindTabHelper::FromWebContents(selection.new_contents);
      if (!HasFindBarController() && find_tab_helper &&
          find_tab_helper->is_find_session_active()) {
        std::ignore = CreateOrGetFindBarController();
      }
      for (const auto& contents : change.GetInsert()->contents) {
        OnTabInsertedAt(contents.contents, contents.index);
      }
      break;
    }
    case TabStripModelChange::kRemoved: {
      for (const auto& contents : change.GetRemove()->contents) {
        if (contents.remove_reason ==
            TabStripModelChange::RemoveReason::kDeleted) {
          OnTabClosing(contents.contents);
        }
        OnTabDetached(contents.contents,
                      contents.contents == selection.old_contents);
      }
      break;
    }
    case TabStripModelChange::kMoved: {
      auto* move = change.GetMove();
      OnTabMoved(move->from_index, move->to_index);
      break;
    }
    case TabStripModelChange::kReplaced: {
      auto* replace = change.GetReplace();
      OnTabReplacedAt(replace->old_contents, replace->new_contents,
                      replace->index);
      break;
    }
    case TabStripModelChange::kSelectionOnly:
      break;
  }

  if (!selection.active_tab_changed()) {
    return;
  }

  if (selection.old_contents) {
    OnTabDeactivated(selection.old_contents);
  }

  if (tab_strip_model_->empty()) {
    return;
  }

  OnActiveTabChanged(
      selection.old_contents, selection.new_contents,
      selection.new_model.active().has_value()
          ? static_cast<int>(selection.new_model.active().value())
          : TabStripModel::kNoTab,
      selection.reason);
}

void Browser::OnTabGroupChanged(const TabGroupChange& change) {
  // If apps ever get tab grouping, this function needs to be updated to
  // retrieve AppSessionService from the correct factory. Additionally,
  // AppSessionService doesn't support SetTabGroupMetadata, so some
  // work to refactor the code to support that into SessionServiceBase
  // would be the best way to achieve that.
  DCHECK(!IsRelevantToAppSessionService(type_));
  DCHECK(tab_strip_model_->group_model());

  if (change.type == TabGroupChange::kVisualsChanged) {
    UpdateTabGroupSessionMetadata(this, change.group);
  } else if (change.type == TabGroupChange::kCreated &&
             change.GetCreateChange()->reason() ==
                 TabGroupChange::TabGroupCreationReason::
                     kInsertedFromAnotherTabstrip) {
    // When a detached group is inserted, we need to update the group of all the
    // corresponding detached tab in session service.
    for (tabs::TabInterface* tab :
         change.GetCreateChange()->GetDetachedTabs()) {
      UpdateTabGroupSessionDataForTab(tab, change.group);
    }
  } else if (change.type == TabGroupChange::kClosed &&
             change.GetCloseChange()->reason() ==
                 TabGroupChange::TabGroupClosureReason::kGroupClosed) {
    // When a group is detached, we do not need to add the information for all
    // the detached tabs in tab restore service.
    sessions::TabRestoreService* tab_restore_service =
        TabRestoreServiceFactory::GetForProfile(profile());
    if (tab_restore_service) {
      tab_restore_service->GroupClosed(change.group);
    }
  }
}

void Browser::TabPinnedStateChanged(TabStripModel* tab_strip_model,
                                    WebContents* contents,
                                    int index) {
  // See comment in Browser::OnTabGroupChanged
  DCHECK(!IsRelevantToAppSessionService(type_));
  SessionService* session_service =
      SessionServiceFactory::GetForProfileIfExisting(profile());
  if (session_service) {
    session_service->SetPinnedState(
        session_id(), sessions::SessionTabHelper::IdForTab(contents),
        tab_strip_model_->IsTabPinned(index));
  }
}

void Browser::TabGroupedStateChanged(
    TabStripModel* tab_strip_model,
    std::optional<tab_groups::TabGroupId> old_group,
    std::optional<tab_groups::TabGroupId> new_group,
    tabs::TabInterface* tab,
    int index) {
  UpdateTabGroupSessionDataForTab(tab, new_group);
}

void Browser::UpdateTabGroupSessionDataForTab(
    tabs::TabInterface* tab,
    std::optional<tab_groups::TabGroupId> group) {
  // See comment in Browser::OnTabGroupChanged
  DCHECK(!IsRelevantToAppSessionService(type_));
  SessionService* const session_service =
      SessionServiceFactory::GetForProfile(profile_);
  if (!session_service) {
    return;
  }

  session_service->SetTabGroup(
      session_id(), sessions::SessionTabHelper::IdForTab(tab->GetContents()),
      std::move(group));
}

void Browser::TabStripEmpty() {
  // Note: even though the tab strip is empty, the call to Close() may not
  // result in closing this Browser. This can happen in the case of closing
  // the last Browser with ongoing downloads.
  window_->Close();
}

void Browser::OnSplitTabChanged(const SplitTabChange& change) {
  switch (change.type) {
    case SplitTabChange::Type::kAdded: {
      for (std::pair<tabs::TabInterface*, int> split_tabs :
           change.GetAddedChange()->tabs()) {
        UpdateSplitTabSessionData(split_tabs.first, change.split_id);
      }

      UpdateSplitTabSessionVisualData(change.split_id);
      break;
    }

    case SplitTabChange::Type::kVisualsChanged: {
      // Update for resize from the handle is done from multicontent view
      // delegate.
      if (!GetBrowserView().multi_contents_view()->IsSplitResizing()) {
        UpdateSplitTabSessionVisualData(change.split_id);
      }
      break;
    }

    case SplitTabChange::Type::kContentsChanged: {
      // No need to do anything here since split is still present and no visual
      // information changed.
      break;
    }

    case SplitTabChange::Type::kRemoved: {
      for (std::pair<tabs::TabInterface*, int> split_tabs :
           change.GetRemovedChange()->tabs()) {
        UpdateSplitTabSessionData(split_tabs.first, std::nullopt);
      }
      break;
    }
  }
}

void Browser::UpdateSplitTabSessionData(
    tabs::TabInterface* tab,
    std::optional<split_tabs::SplitTabId> split_id) {
  DCHECK(!IsRelevantToAppSessionService(type_));
  SessionService* const session_service =
      SessionServiceFactory::GetForProfile(profile_);
  if (!session_service) {
    return;
  }

  session_service->SetSplitTab(
      session_id(), sessions::SessionTabHelper::IdForTab(tab->GetContents()),
      std::move(split_id));
}

void Browser::UpdateSplitTabSessionVisualData(
    const split_tabs::SplitTabId& split_id) {
  SessionService* const session_service =
      SessionServiceFactory::GetForProfile(profile());
  if (!session_service) {
    return;
  }

  const split_tabs::SplitTabVisualData* visual_data =
      tab_strip_model()->GetSplitData(split_id)->visual_data();
  session_service->SetSplitTabData(session_id(), split_id, visual_data);
}

void Browser::SetTopControlsShownRatio(content::WebContents* web_contents,
                                       float ratio) {
  window_->SetTopControlsShownRatio(web_contents, ratio);
}

int Browser::GetTopControlsHeight() {
  return window_->GetTopControlsHeight();
}

bool Browser::DoBrowserControlsShrinkRendererSize(
    content::WebContents* contents) {
  return window_->DoBrowserControlsShrinkRendererSize(contents);
}

int Browser::GetVirtualKeyboardHeight(content::WebContents* contents) {
  // This API is currently only used by View Transitions when the virtual
  // keyboard resizes content.  On desktop platforms, the virtual keyboard can
  // only inset the visual viewport so it shouldn't ever be called.
  NOTIMPLEMENTED();
  return 0;
}

void Browser::SetTopControlsGestureScrollInProgress(bool in_progress) {
  window_->SetTopControlsGestureScrollInProgress(in_progress);
}

bool Browser::CanOverscrollContent() {
#if defined(USE_AURA)
  return GetFeatures().overscroll_pref_manager()->CanOverscrollContent();
#else
  return false;
#endif
}

bool Browser::ShouldPreserveAbortedURLs(WebContents* source) {
  // Allow failed URLs to stick around in the omnibox on the NTP, but not when
  // other pages have committed.
  Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext());
  if (!profile || !source->GetController().GetLastCommittedEntry()) {
    return false;
  }
  GURL committed_url(source->GetController().GetLastCommittedEntry()->GetURL());
  return search::IsNTPOrRelatedURL(committed_url, profile);
}

void Browser::SetFocusToLocationBar() {
  // Two differences between this and FocusLocationBar():
  // (1) This doesn't get recorded in user metrics, since it's called
  //     internally.
  // (2) This is called with |is_user_initiated| == false, because this is a
  //     renderer initiated focus (this method is a WebContentsDelegate
  //     override).
  window_->SetFocusToLocationBar(false);
}

void Browser::PreHandleDragUpdate(const content::DropData& drop_data,
                                  const gfx::PointF& client_pt) {
  window()->PreHandleDragUpdate(drop_data, client_pt);
}

void Browser::PreHandleDragExit() {
  window()->PreHandleDragExit();
}

void Browser::HandleDragEnded() {
  window()->HandleDragEnded();
}

content::KeyboardEventProcessingResult Browser::PreHandleKeyboardEvent(
    content::WebContents* source,
    const NativeWebKeyboardEvent& event) {
  // Forward keyboard events to the manager for fullscreen / mouse lock. This
  // may consume the event (e.g., Esc exits fullscreen mode).
  // TODO(koz): Write a test for this http://crbug.com/100441.
  if (browser_window_features()->exclusive_access_manager()->HandleUserKeyEvent(
          event)) {
    return content::KeyboardEventProcessingResult::HANDLED;
  }

  return window()->PreHandleKeyboardEvent(event);
}

bool Browser::HandleKeyboardEvent(content::WebContents* source,
                                  const NativeWebKeyboardEvent& event) {
  DevToolsWindow* devtools_window =
      DevToolsWindow::GetInstanceForInspectedWebContents(source);
  return (devtools_window && devtools_window->ForwardKeyboardEvent(event)) ||
         window()->HandleKeyboardEvent(event);
}

bool Browser::TabsNeedBeforeUnloadFired() const {
  return unload_controller_.TabsNeedBeforeUnloadFired();
}

bool Browser::PreHandleGestureEvent(content::WebContents* source,
                                    const blink::WebGestureEvent& event) {
  // Disable pinch zooming in undocked dev tools window due to poor UX.
  if (app_name() == DevToolsWindow::kDevToolsApp) {
    return blink::WebInputEvent::IsPinchGestureEventType(event.GetType());
  }
  return false;
}

bool Browser::CanDragEnter(content::WebContents* source,
                           const content::DropData& data,
                           blink::DragOperationsMask operations_allowed) {
#if BUILDFLAG(IS_CHROMEOS)
  // Disallow drag-and-drop navigation for Settings windows which do not support
  // external navigation.
  if ((operations_allowed & blink::kDragOperationLink) &&
      chrome::SettingsWindowManager::GetInstance()->IsSettingsBrowser(this)) {
    return false;
  }
#endif
  return true;
}

void Browser::CreateSmsPrompt(content::RenderFrameHost*,
                              const std::vector<url::Origin>&,
                              const std::string& one_time_code,
                              base::OnceClosure on_confirm,
                              base::OnceClosure on_cancel) {
  // TODO(crbug.com/40103792): implementation left pending deliberately.
  std::move(on_confirm).Run();
}

bool Browser::ShouldAllowRunningInsecureContent(
    content::WebContents* web_contents,
    bool allowed_per_prefs,
    const url::Origin& origin,
    const GURL& resource_url) {
  // Note: this implementation is a mirror of
  // ContentSettingsObserver::allowRunningInsecureContent.
  if (allowed_per_prefs) {
    return true;
  }

  Profile* profile =
      Profile::FromBrowserContext(web_contents->GetBrowserContext());
  HostContentSettingsMap* content_settings =
      HostContentSettingsMapFactory::GetForProfile(profile);
  return content_settings->GetContentSetting(
             web_contents->GetLastCommittedURL(), GURL(),
             ContentSettingsType::MIXEDSCRIPT) == CONTENT_SETTING_ALLOW;
}

void Browser::OnDidBlockNavigation(
    content::WebContents* web_contents,
    const GURL& blocked_url,
    blink::mojom::NavigationBlockedReason reason) {
  if (reason ==
      blink::mojom::NavigationBlockedReason::kRedirectWithNoUserGesture) {
    if (auto* framebust_helper =
            FramebustBlockTabHelper::FromWebContents(web_contents)) {
      auto on_click = [](const GURL& url, size_t index, size_t total_elements) {
        UMA_HISTOGRAM_ENUMERATION(
            "WebCore.Framebust.ClickThroughPosition",
            blocked_content::GetListItemPositionFromDistance(index,
                                                             total_elements));
      };
      framebust_helper->AddBlockedUrl(blocked_url, base::BindOnce(on_click));
    }
  }
}

content::PictureInPictureResult Browser::EnterPictureInPicture(
    content::WebContents* web_contents) {
  return PictureInPictureWindowManager::GetInstance()
      ->EnterVideoPictureInPicture(web_contents);
}

void Browser::ExitPictureInPicture() {
  PictureInPictureWindowManager::GetInstance()->ExitPictureInPicture();
}

bool Browser::IsBackForwardCacheSupported(content::WebContents& web_contents) {
  return true;
}

content::PreloadingEligibility Browser::IsPrerender2Supported(
    content::WebContents& web_contents,
    content::PreloadingTriggerType trigger_type) {
  Profile* profile =
      Profile::FromBrowserContext(web_contents.GetBrowserContext());
  return prefetch::IsSomePreloadingEnabled(*profile->GetPrefs());
}

bool Browser::ShouldShowStaleContentOnEviction(content::WebContents* source) {
#if BUILDFLAG(IS_CHROMEOS)
  return source == tab_strip_model_->GetActiveWebContents();
#else
  return false;
#endif  // BUILDFLAG(IS_CHROMEOS)
}

bool Browser::IsPointerLocked() const {
  return browser_window_features()
      ->exclusive_access_manager()
      ->pointer_lock_controller()
      ->IsPointerLocked();
}

void Browser::OnWindowDidShow() {
  if (window_has_shown_) {
    return;
  }
  window_has_shown_ = true;

  startup_metric_utils::GetBrowser().RecordBrowserWindowDisplay(
      base::TimeTicks::Now());

  // Nothing to do for non-tabbed windows.
  if (!is_type_normal()) {
    return;
  }

  // Show any pending global error bubble.
  GlobalErrorService* service =
      GlobalErrorServiceFactory::GetForProfile(profile());
  GlobalError* error = service->GetFirstGlobalErrorWithBubbleView();
  if (error) {
    error->ShowBubbleView(this);
  }
}

///////////////////////////////////////////////////////////////////////////////
// Browser, content::WebContentsDelegate implementation:

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

  if (is_type_devtools()) {
    DevToolsWindow* window = DevToolsWindow::AsDevToolsWindow(source);
    DCHECK(window);
    return window->OpenURLFromTab(source, params,
                                  std::move(navigation_handle_callback));
  }

  NavigateParams nav_params(this, params.url, params.transition);
  nav_params.FillNavigateParamsFromOpenURLParams(params);
  nav_params.source_contents = source;
  nav_params.tabstrip_add_types = AddTabTypes::ADD_NONE;
  if (params.user_gesture) {
    nav_params.window_action = NavigateParams::WindowAction::kShowWindow;
  }
  bool is_popup =
      source && blocked_content::ConsiderForPopupBlocking(params.disposition);
  auto popup_delegate =
      std::make_unique<ChromePopupNavigationDelegate>(std::move(nav_params));
  if (is_popup) {
    popup_delegate.reset(static_cast<ChromePopupNavigationDelegate*>(
        blocked_content::MaybeBlockPopup(
            source, nullptr, std::move(popup_delegate), &params,
            blink::mojom::WindowFeatures(),
            HostContentSettingsMapFactory::GetForProfile(
                source->GetBrowserContext()))
            .release()));
    if (!popup_delegate) {
      return nullptr;
    }
  }

  chrome::ConfigureTabGroupForNavigation(popup_delegate->nav_params());

  base::WeakPtr<content::NavigationHandle> navigation_handle =
      Navigate(popup_delegate->nav_params());

  if (navigation_handle_callback && navigation_handle) {
    std::move(navigation_handle_callback).Run(*navigation_handle);
  }

  content::WebContents* navigated_or_inserted_contents =
      popup_delegate->nav_params()->navigated_or_inserted_contents;
  if (is_popup && navigated_or_inserted_contents) {
    auto* tracker = blocked_content::PopupTracker::CreateForWebContents(
        navigated_or_inserted_contents, source, params.disposition);
    tracker->set_is_trusted(
        params.triggering_event_info !=
        blink::mojom::TriggeringEventInfo::kFromUntrustedEvent);
  }

  TRACE_EVENT_INSTANT1(
      "navigation", "Browser::OpenURLFromTab_Result", TRACE_EVENT_SCOPE_THREAD,
      "navigated_or_inserted_contents", navigated_or_inserted_contents);

  return navigated_or_inserted_contents;
}

void Browser::NavigationStateChanged(WebContents* source,
                                     content::InvalidateTypes changed_flags) {
  // If we're shutting down we should refuse to process this message.
  // See crbug.com/1306297; it's possible that a WebContents sends navigation
  // state messages while destructing during browser tear-down. Ironically we
  // can't use IsShuttingDown() because by this point the browser is entirely
  // removed from the browser list.
  if (is_delete_scheduled_) {
    return;
  }

  // Only update the UI when something visible has changed.
  if (changed_flags) {
    ScheduleUIUpdate(source, changed_flags);
  }

  // We can synchronously update commands since they will only change once per
  // navigation, so we don't have to worry about flickering. We do, however,
  // need to update the command state early on load to always present usable
  // actions in the face of slow-to-commit pages.
  if (changed_flags &
      (content::INVALIDATE_TYPE_URL | content::INVALIDATE_TYPE_LOAD |
       content::INVALIDATE_TYPE_TAB)) {
    GetCommandController()->TabStateChanged();
  }

  if (auto* const app_browser_controller = GetAppBrowserController();
      app_browser_controller) {
    app_browser_controller->UpdateCustomTabBarVisibility(true);
  }
}

void Browser::VisibleSecurityStateChanged(WebContents* source) {
  // When the current tab's security state changes, we need to update the URL
  // bar to reflect the new state.
  DCHECK(source);
  if (tab_strip_model_->GetActiveWebContents() == source) {
    UpdateToolbarSecurityState();

    if (auto* const app_browser_controller = GetAppBrowserController();
        app_browser_controller) {
      app_browser_controller->UpdateCustomTabBarVisibility(true);
    }
  }
}

content::WebContents* Browser::AddNewContents(
    WebContents* source,
    std::unique_ptr<WebContents> new_contents,
    const GURL& target_url,
    WindowOpenDisposition disposition,
    const blink::mojom::WindowFeatures& window_features,
    bool user_gesture,
    bool* was_blocked) {
  FullscreenController* fullscreen_controller = browser_window_features()
                                                    ->exclusive_access_manager()
                                                    ->fullscreen_controller();
#if BUILDFLAG(IS_MAC)
  // On the Mac, the convention is to turn popups into new tabs when in browser
  // fullscreen mode. Only worry about user-initiated fullscreen as showing a
  // popup in HTML5 fullscreen would have kicked the page out of fullscreen.
  // However if this Browser is for an app or the popup is being requested on a
  // different display, we don't want to turn popups into new tabs. Popups
  // should open as new windows instead.
  display::Screen* screen = display::Screen::Get();
  bool targeting_different_display =
      screen && source && source->GetContentNativeView() &&
      screen->GetDisplayNearestView(source->GetContentNativeView()) !=
          screen->GetDisplayMatching(window_features.bounds);
  if (!GetAppBrowserController() &&
      disposition == WindowOpenDisposition::NEW_POPUP &&
      fullscreen_controller->IsFullscreenForBrowser() &&
      !targeting_different_display) {
    disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
  }
#endif

  // At this point the |new_contents| is beyond the popup blocker, but we use
  // the same logic for determining if the popup tracker needs to be attached.
  if (source && blocked_content::ConsiderForPopupBlocking(disposition)) {
    blocked_content::PopupTracker::CreateForWebContents(new_contents.get(),
                                                        source, disposition);
  }

  // Postpone activating popups opened by content-fullscreen tabs. This permits
  // popups on other screens and retains fullscreen focus for exit accelerators.
  // Popups are activated when the opener exits fullscreen, which happens
  // immediately if the popup would overlap the fullscreen window.
  // Allow fullscreen-within-tab openers to open popups normally.
  NavigateParams::WindowAction window_action =
      NavigateParams::WindowAction::kShowWindow;
  if (disposition == WindowOpenDisposition::NEW_POPUP &&
      GetFullscreenState(source).target_mode ==
          content::FullscreenMode::kContent) {
    window_action = NavigateParams::WindowAction::kShowWindowInactive;
    fullscreen_controller->FullscreenTabOpeningPopup(source,
                                                     new_contents.get());
    // Defer popup creation if the opener has a fullscreen transition in
    // progress. This works around a defect on Mac where separate displays
    // cannot switch their independent spaces simultaneously (crbug.com/1315749)
    auto web_contents_creation_callback = base::BindOnce(
        &chrome::AddWebContents, this, source, std::move(new_contents),
        target_url, disposition, window_features, window_action, user_gesture);
    fullscreen_controller->RunOrDeferUntilTransitionIsComplete(base::BindOnce(
        base::IgnoreResult(std::move(web_contents_creation_callback))));
    return nullptr;
  }

  return chrome::AddWebContents(this, source, std::move(new_contents),
                                target_url, disposition, window_features,
                                window_action, user_gesture);
}

void Browser::ActivateContents(WebContents* contents) {
  // A WebContents can ask to activate after it's been removed from the
  // TabStripModel. See https://crbug.com/1060986
  int index = tab_strip_model_->GetIndexOfWebContents(contents);
  if (index == TabStripModel::kNoTab) {
    return;
  }
  tab_strip_model_->ActivateTabAt(index);
  window_->Activate();
}

bool Browser::IsContentsActive(content::WebContents* contents) {
  return tab_strip_model_->GetActiveWebContents() == contents;
}

void Browser::LoadingStateChanged(WebContents* source,
                                  bool should_show_loading_ui) {
  ScheduleUIUpdate(source, content::INVALIDATE_TYPE_LOAD);
  UpdateWindowForLoadingStateChanged(source, should_show_loading_ui);
}

void Browser::CloseContents(WebContents* source) {
  if (unload_controller_.CanCloseContents(source)) {
    chrome::CloseWebContents(this, source, true);
  }
}

void Browser::SetContentsBounds(WebContents* source, const gfx::Rect& bounds) {
  if (is_type_normal()) {
    return;
  }

  std::vector<blink::mojom::WebFeature> features = {
      blink::mojom::WebFeature::kMovedOrResizedPopup};
  if (creation_timer_.Elapsed() > base::Seconds(2)) {
    // Additionally measure whether a popup was moved after creation, to
    // distinguish between popups that reposition themselves after load and
    // those which move popups continuously.
    features.push_back(
        blink::mojom::WebFeature::kMovedOrResizedPopup2sAfterCreation);
  }

  page_load_metrics::MetricsWebContentsObserver::RecordFeatureUsage(
      source->GetPrimaryMainFrame(), std::move(features));
  window_->SetBounds(bounds);
}

void Browser::UpdateTargetURL(WebContents* source, const GURL& url) {
  std::vector<StatusBubble*> status_bubbles = GetStatusBubbles();
  for (StatusBubble* status_bubble : status_bubbles) {
    StatusBubbleViews* status_bubble_views =
        static_cast<StatusBubbleViews*>(status_bubble);
    ContentsWebView* anchor =
        static_cast<ContentsWebView*>(status_bubble_views->base_view());
    if (source == anchor->GetWebContents()) {
      status_bubble->SetURL(url);
      break;
    }
  }
}

void Browser::ContentsMouseEvent(WebContents* source, const ui::Event& event) {
  const ui::EventType type = event.type();
  const bool exited = type == ui::EventType::kMouseExited;
  // Disregard synthesized events, and mouse enter and exit, which may occur
  // without explicit user input events during window state changes.
  if (type != ui::EventType::kMouseEntered && !exited &&
      !event.IsSynthesized()) {
    browser_window_features()->exclusive_access_manager()->OnUserInput();
  }

  // Mouse motion events update the status bubble, if it exists.
  std::vector<StatusBubble*> status_bubbles = GetStatusBubbles();
  for (StatusBubble* status_bubble : status_bubbles) {
    StatusBubbleViews* status_bubble_views =
        static_cast<StatusBubbleViews*>(status_bubble);
    ContentsWebView* anchor =
        static_cast<ContentsWebView*>(status_bubble_views->base_view());
    if (source == anchor->GetWebContents() &&
        (type == ui::EventType::kMouseMoved || exited)) {
      status_bubble->MouseMoved(exited);
      if (exited) {
        status_bubble->SetURL(GURL());
      }
      break;
    }
  }
}

void Browser::ContentsZoomChange(bool zoom_in) {
  chrome::ExecuteCommand(this, zoom_in ? IDC_ZOOM_PLUS : IDC_ZOOM_MINUS);
}

bool Browser::TakeFocus(content::WebContents* source, bool reverse) {
  return false;
}

bool Browser::DidAddMessageToConsole(
    content::WebContents* source,
    blink::mojom::ConsoleMessageLevel log_level,
    const std::u16string& message,
    int32_t line_no,
    const std::u16string& source_id) {
  static bool is_headless_mode = headless::IsHeadlessMode();
  if (is_headless_mode) {
    const bool is_builtin_component = !!source->GetWebUI();
    headless::LogConsoleMessage(log_level, message, line_no,
                                is_builtin_component, source_id);
    return true;
  }
  return false;
}

void Browser::BeforeUnloadFired(WebContents* web_contents,
                                bool proceed,
                                bool* proceed_to_fire_unload) {
  if (is_type_devtools() &&
      DevToolsWindow::HandleBeforeUnload(web_contents, proceed,
                                         proceed_to_fire_unload)) {
    return;
  }

  *proceed_to_fire_unload =
      unload_controller_.BeforeUnloadFired(web_contents, proceed);
}

bool Browser::ShouldFocusLocationBarByDefault(WebContents* source) {
  // Navigations in background tabs shouldn't change the focus state of the
  // omnibox, since it's associated with the foreground tab.
  if (source != tab_strip_model_->GetActiveWebContents()) {
    return false;
  }

  // This should be based on the pending entry if there is one, so that
  // back/forward navigations to the NTP are handled.  The visible entry can't
  // be used here, since back/forward navigations are not treated as visible
  // entries to avoid URL spoofs.
  content::NavigationEntry* entry =
      source->GetController().GetPendingEntry()
          ? source->GetController().GetPendingEntry()
          : source->GetController().GetLastCommittedEntry();
  if (entry) {
    const GURL& url = entry->GetURL();
    const GURL& virtual_url = entry->GetVirtualURL();

    if (virtual_url.SchemeIs(content::kViewSourceScheme)) {
      return false;
    }

    if ((url.SchemeIs(content::kChromeUIScheme) &&
         url.host() == chrome::kChromeUINewTabHost) ||
        (virtual_url.SchemeIs(content::kChromeUIScheme) &&
         virtual_url.host() == chrome::kChromeUINewTabHost)) {
      return true;
    }

    if (url.spec() == chrome::kChromeUISplitViewNewTabPageURL) {
      return true;
    }
  }

  return search::NavEntryIsInstantNTP(source, entry);
}

bool Browser::ShouldFocusPageAfterCrash(WebContents* source) {
  // Focus only the active page when reloading after a crash, otherwise
  // return false. This is to ensure background reloads via hovercard
  // don't end up causing a focus loss which results in its dismissal.
  return source == tab_strip_model_->GetActiveWebContents();
}

void Browser::ShowRepostFormWarningDialog(WebContents* source) {
  TabModalConfirmDialog::Create(
      std::make_unique<RepostFormWarningController>(source), source);
}

bool Browser::IsWebContentsCreationOverridden(
    content::RenderFrameHost* opener,
    content::SiteInstance* source_site_instance,
    content::mojom::WindowContainerType window_container_type,
    const GURL& opener_url,
    const std::string& frame_name,
    const GURL& target_url) {
  if (HasActorTask(profile(), opener)) {
    // If an ExecutionEngine is acting on the opener, prevent it from creating a
    // new WebContents. We'll instead force the navigation to happen in the same
    // tab. Note, we do this even if the task isn't active (e.g. paused) so that
    // a user action on behalf of the actor has the same behavior since the
    // resumed task will still be fixed to the tab.
    return true;
  }

  return (window_container_type ==
              content::mojom::WindowContainerType::BACKGROUND &&
          ShouldCreateBackgroundContents(source_site_instance, opener_url,
                                         frame_name));
}

WebContents* Browser::CreateCustomWebContents(
    content::RenderFrameHost* opener,
    content::SiteInstance* source_site_instance,
    bool is_new_browsing_instance,
    const GURL& opener_url,
    const std::string& frame_name,
    const GURL& target_url,
    const content::StoragePartitionConfig& partition_config,
    content::SessionStorageNamespace* session_storage_namespace) {
  if (auto* opener_contents = content::WebContents::FromRenderFrameHost(opener);
      HasActorTask(profile(), opener)) {
    // If an ExecutionEngine is acting on the opener, we force the navigation
    // to happen in the same tab.
    content::NavigationController::LoadURLParams params(target_url);
    params.initiator_frame_token = opener->GetFrameToken();
    params.initiator_process_id = opener->GetProcess()->GetDeprecatedID();
    params.initiator_origin = opener->GetLastCommittedOrigin();
    params.source_site_instance = source_site_instance;
    params.transition_type = ui::PAGE_TRANSITION_LINK;
    params.is_renderer_initiated = true;
    opener_contents->GetController().LoadURLWithParams(params);
    VLOG(1) << "Actor treated window open as same tab navigation. "
            << target_url;
    return nullptr;
  }

  BackgroundContents* background_contents = CreateBackgroundContents(
      source_site_instance, opener, opener_url, is_new_browsing_instance,
      frame_name, target_url, partition_config, session_storage_namespace);
  if (background_contents) {
    return background_contents->web_contents();
  }
  return nullptr;
}

void Browser::WebContentsCreated(WebContents* source_contents,
                                 int opener_render_process_id,
                                 int opener_render_frame_id,
                                 const std::string& frame_name,
                                 const GURL& target_url,
                                 WebContents* new_contents) {
  // Note: Consult owners before adding new code here.
  // This method is called from WebContentsImpl::CreateNewWindow() for a created
  // `new_contents`. This occurs before ownership of `new_contents` is
  // transferred to Browser and `new_contents` is added to a TabModel. Tab
  // specific initialization should be performed by TabModel and not added here.

  // SafeBrowsingNavigationObserver relies on recording a precise sequence of
  // navigation events, with tabs tracked via their SessionID, managed by
  // SessionTabHelper. The current safe browsing implementation requires
  // tracking new contents from the moment of creation, at which point TabModel
  // and tab helpers have not yet been initialized for `new_contents`.
  // Explicitly instantiate the SessionTabHelper here to ensure SessionIDs are
  // available when needed.
  // TODO(crbug.com/362038317): Once SafeBrowsingNavigationObserver is updated
  // to track `new_contents` after it is added to its TabModel this override can
  // be removed.
  CreateSessionServiceTabHelper(new_contents);
}

void Browser::RendererUnresponsive(
    WebContents* source,
    content::RenderWidgetHost* render_widget_host,
    base::RepeatingClosure hang_monitor_restarter) {
  // Don't show the page hung dialog when a HTML popup hangs because
  // the dialog will take the focus and immediately close the popup.
  RenderWidgetHostView* view = render_widget_host->GetView();
  if (view && !render_widget_host->GetView()->IsHTMLFormPopup()) {
    TabDialogs::FromWebContents(source)->ShowHungRendererDialog(
        render_widget_host, std::move(hang_monitor_restarter));
  }
}

void Browser::RendererResponsive(
    WebContents* source,
    content::RenderWidgetHost* render_widget_host) {
  RenderWidgetHostView* view = render_widget_host->GetView();
  if (view && !render_widget_host->GetView()->IsHTMLFormPopup()) {
    TabDialogs::FromWebContents(source)->HideHungRendererDialog(
        render_widget_host);
  }
}

content::JavaScriptDialogManager* Browser::GetJavaScriptDialogManager(
    WebContents* source) {
  return javascript_dialogs::TabModalDialogManager::FromWebContents(source);
}

bool Browser::GuestSaveFrame(content::WebContents* guest_web_contents) {
  auto* guest_view =
      extensions::MimeHandlerViewGuest::FromWebContents(guest_web_contents);
  return guest_view && guest_view->PluginDoSave();
}

std::unique_ptr<content::EyeDropper> Browser::OpenEyeDropper(
    content::RenderFrameHost* frame,
    content::EyeDropperListener* listener) {
  return window()->OpenEyeDropper(frame, listener);
}

void Browser::InitiatePreview(content::WebContents& web_contents,
                              const GURL& url) {
#if !BUILDFLAG(IS_ANDROID)
  PreviewManager::CreateForWebContents(&web_contents);
  PreviewManager* manager = PreviewManager::FromWebContents(&web_contents);
  CHECK(manager);
  manager->InitiatePreview(url);
#endif
}

bool Browser::ShouldUseInstancedSystemMediaControls() const {
  return is_type_app() || is_type_app_popup();
}

void Browser::DraggableRegionsChanged(
    const std::vector<blink::mojom::DraggableRegionPtr>& regions,
    content::WebContents* contents) {
  if (auto* const app_browser_controller = GetAppBrowserController();
      app_browser_controller) {
    app_browser_controller->DraggableRegionsChanged(regions, contents);
  }
}

std::vector<blink::mojom::RelatedApplicationPtr>
Browser::GetSavedRelatedApplications(WebContents* web_contents) {
  Profile* profile =
      Profile::FromBrowserContext(web_contents->GetBrowserContext());
  CHECK(profile);
  if (!web_app::AreWebAppsEnabled(profile)) {
    return {};
  }
  const webapps::AppId* app_id =
      web_app::WebAppTabHelper::GetAppId(web_contents);
  if (!app_id || app_id->empty()) {
    return {};
  }
  web_app::WebAppProvider* provider =
      web_app::WebAppProvider::GetForWebApps(profile);
  CHECK(provider);
  std::vector<blink::Manifest::RelatedApplication> saved_related_apps =
      provider->registrar_unsafe().GetRelatedApplications(*app_id);
  std::vector<blink::mojom::RelatedApplicationPtr> related_apps_ptr;
  for (const auto& app : saved_related_apps) {
    auto related_app = blink::mojom::RelatedApplication::New();
    related_app->platform =
        base::UTF16ToUTF8(app.platform.value_or(std::u16string()));
    related_app->id = base::UTF16ToUTF8(app.id.value_or(std::u16string()));
    if (!app.url.is_empty()) {
      related_app->url = app.url.spec();
    }
    related_apps_ptr.push_back(std::move(related_app));
  }
  return related_apps_ptr;
}

content::WebContents* Browser::GetResponsibleWebContents(
    content::WebContents* web_contents) {
  // Tabs are the proper choice for modal scope.
  return web_contents;
}

void Browser::RunFileChooser(
    content::RenderFrameHost* render_frame_host,
    scoped_refptr<content::FileSelectListener> listener,
    const blink::mojom::FileChooserParams& params) {
  FileSelectHelper::RunFileChooser(render_frame_host, std::move(listener),
                                   params);
}

void Browser::EnumerateDirectory(
    WebContents* web_contents,
    scoped_refptr<content::FileSelectListener> listener,
    const base::FilePath& path) {
  FileSelectHelper::EnumerateDirectory(web_contents, std::move(listener), path);
}

bool Browser::CanUseWindowingControls(
    content::RenderFrameHost* requesting_frame) {
  if (!GetAppBrowserController()) {
    requesting_frame->AddMessageToConsole(
        blink::mojom::ConsoleMessageLevel::kWarning,
        "API called from something else than a web_app.");
    return false;
  }
  return true;
}

void Browser::OnWebApiWindowResizableChanged() {
  window_->OnWebApiWindowResizableChanged();
}

bool Browser::GetCanResize() {
  return window_->GetCanResize();
}

void Browser::MinimizeFromWebAPI() {
  window_->Minimize();
}

void Browser::MaximizeFromWebAPI() {
  window_->Maximize();
}

void Browser::RestoreFromWebAPI() {
  window_->Restore();
}

ui::mojom::WindowShowState Browser::GetWindowShowState() const {
  return window_->GetWindowShowState();
}

bool Browser::CanEnterFullscreenModeForTab(
    content::RenderFrameHost* requesting_frame) {
  // If the tab strip isn't editable then a drag session is in progress, and it
  // is not safe to enter fullscreen. https://crbug.com/1315080
  if (!tab_strip_model_delegate_->IsTabStripEditable()) {
    return false;
  }

  return browser_window_features()
      ->exclusive_access_manager()
      ->fullscreen_controller()
      ->CanEnterFullscreenModeForTab(requesting_frame);
}

void Browser::EnterFullscreenModeForTab(
    content::RenderFrameHost* requesting_frame,
    const blink::mojom::FullscreenOptions& options) {
  browser_window_features()
      ->exclusive_access_manager()
      ->fullscreen_controller()
      ->EnterFullscreenModeForTab(requesting_frame,
                                  FullscreenTabParams{options.display_id});
}

void Browser::ExitFullscreenModeForTab(WebContents* web_contents) {
  browser_window_features()
      ->exclusive_access_manager()
      ->fullscreen_controller()
      ->ExitFullscreenModeForTab(web_contents);
}

bool Browser::IsFullscreenForTabOrPending(const WebContents* web_contents) {
  const content::FullscreenState state = GetFullscreenState(web_contents);
  return state.target_mode == content::FullscreenMode::kContent ||
         state.target_mode == content::FullscreenMode::kPseudoContent;
}

content::FullscreenState Browser::GetFullscreenState(
    const WebContents* web_contents) const {
  return browser_window_features()
      ->exclusive_access_manager()
      ->fullscreen_controller()
      ->GetFullscreenState(web_contents);
}

blink::mojom::DisplayMode Browser::GetDisplayMode(
    const WebContents* web_contents) {
  if (window_->IsFullscreen()) {
    return blink::mojom::DisplayMode::kFullscreen;
  }

  if (is_type_picture_in_picture()) {
    return blink::mojom::DisplayMode::kPictureInPicture;
  }

  if (is_type_app() || is_type_devtools() || is_type_app_popup()) {
    auto* const app_browser_controller = GetAppBrowserController();
    if (app_browser_controller &&
        app_browser_controller->HasMinimalUiButtons()) {
      return blink::mojom::DisplayMode::kMinimalUi;
    }

    if (app_browser_controller &&
        app_browser_controller->AppUsesWindowControlsOverlay() &&
        !web_contents->GetWindowsControlsOverlayRect().IsEmpty()) {
      return blink::mojom::DisplayMode::kWindowControlsOverlay;
    }

    if (app_browser_controller && app_browser_controller->AppUsesTabbed()) {
      return blink::mojom::DisplayMode::kTabbed;
    }

    if (app_browser_controller &&
        app_browser_controller->AppUsesBorderlessMode() &&
        window_->IsBorderlessModeEnabled()) {
      return blink::mojom::DisplayMode::kBorderless;
    }

    return blink::mojom::DisplayMode::kStandalone;
  }

  return blink::mojom::DisplayMode::kBrowser;
}

blink::ProtocolHandlerSecurityLevel Browser::GetProtocolHandlerSecurityLevel(
    content::RenderFrameHost* requesting_frame) {
  content::BrowserContext* context = requesting_frame->GetBrowserContext();
  extensions::ProcessMap* process_map = extensions::ProcessMap::Get(context);
  const Extension* owner_extension =
      extensions::ProcessManager::Get(context)->GetExtensionForRenderFrameHost(
          requesting_frame);
  if (owner_extension &&
      process_map->IsPrivilegedExtensionProcess(
          *owner_extension,
          requesting_frame->GetProcess()->GetDeprecatedID())) {
    return blink::ProtocolHandlerSecurityLevel::kExtensionFeatures;
  }
  return blink::ProtocolHandlerSecurityLevel::kStrict;
}

void Browser::RegisterProtocolHandler(
    content::RenderFrameHost* requesting_frame,
    const std::string& protocol,
    const GURL& url,
    bool user_gesture) {
  content::BrowserContext* context = requesting_frame->GetBrowserContext();
  if (context->IsOffTheRecord()) {
    return;
  }

  auto* web_contents =
      content::WebContents::FromRenderFrameHost(requesting_frame);

  ProtocolHandler handler = ProtocolHandler::CreateProtocolHandler(
      protocol, url, GetProtocolHandlerSecurityLevel(requesting_frame));

  // The parameters's normalization process defined in the spec has been already
  // applied in the WebContentImpl class, so at this point it shouldn't be
  // possible to create an invalid handler.
  // https://html.spec.whatwg.org/multipage/system-state.html#normalize-protocol-handler-parameters
  DCHECK(handler.IsValid());

  custom_handlers::ProtocolHandlerRegistry* registry =
      ProtocolHandlerRegistryFactory::GetForBrowserContext(context);
  if (registry->SilentlyHandleRegisterHandlerRequest(handler)) {
    return;
  }

  // TODO(carlscab): This should probably be FromFrame() once it becomes
  // PageSpecificContentSettingsDelegate
  auto* page_content_settings_delegate =
      PageSpecificContentSettingsDelegate::FromWebContents(web_contents);
  if (!user_gesture && window_) {
    page_content_settings_delegate->set_pending_protocol_handler(handler);
    page_content_settings_delegate->set_previous_protocol_handler(
        registry->GetHandlerFor(handler.protocol()));
    window_->GetLocationBar()->UpdateContentSettingsIcons();
    return;
  }

  // Make sure content-setting icon is turned off in case the page does
  // ungestured and gestured RPH calls.
  if (window_) {
    page_content_settings_delegate->ClearPendingProtocolHandler();
    window_->GetLocationBar()->UpdateContentSettingsIcons();
  }

  if (registry->registration_mode() ==
      custom_handlers::RphRegistrationMode::kAutoAccept) {
    registry->OnAcceptRegisterProtocolHandler(handler);
    return;
  }

  permissions::PermissionRequestManager* permission_request_manager =
      permissions::PermissionRequestManager::FromWebContents(web_contents);
  if (permission_request_manager) {
    // At this point, there will be UI presented, and running a dialog causes an
    // exit to webpage-initiated fullscreen. http://crbug.com/728276
    base::ScopedClosureRunner fullscreen_block =
        web_contents->ForSecurityDropFullscreen(
            /*display_id=*/display::kInvalidDisplayId);

    permission_request_manager->AddRequest(
        requesting_frame,
        std::make_unique<
            custom_handlers::RegisterProtocolHandlerPermissionRequest>(
            registry, handler, url, std::move(fullscreen_block)));
  }
}

void Browser::UnregisterProtocolHandler(
    content::RenderFrameHost* requesting_frame,
    const std::string& protocol,
    const GURL& url,
    bool user_gesture) {
  // user_gesture will be used in case we decide to have confirmation bubble
  // for user while un-registering the handler.
  content::BrowserContext* context = requesting_frame->GetBrowserContext();
  if (context->IsOffTheRecord()) {
    return;
  }

  ProtocolHandler handler = ProtocolHandler::CreateProtocolHandler(
      protocol, url, GetProtocolHandlerSecurityLevel(requesting_frame));

  custom_handlers::ProtocolHandlerRegistry* registry =
      ProtocolHandlerRegistryFactory::GetForBrowserContext(context);
  registry->RemoveHandler(handler);
}

void Browser::FindReply(WebContents* web_contents,
                        int request_id,
                        int number_of_matches,
                        const gfx::Rect& selection_rect,
                        int active_match_ordinal,
                        bool final_update) {
  find_in_page::FindTabHelper* find_tab_helper =
      find_in_page::FindTabHelper::FromWebContents(web_contents);
  if (!find_tab_helper) {
    return;
  }

  find_tab_helper->HandleFindReply(request_id, number_of_matches,
                                   selection_rect, active_match_ordinal,
                                   final_update);
}

void Browser::RequestPointerLock(WebContents* web_contents,
                                 bool user_gesture,
                                 bool last_unlocked_by_target) {
  browser_window_features()
      ->exclusive_access_manager()
      ->pointer_lock_controller()
      ->RequestToLockPointer(web_contents, user_gesture,
                             last_unlocked_by_target);
}

void Browser::LostPointerLock() {
  browser_window_features()
      ->exclusive_access_manager()
      ->pointer_lock_controller()
      ->ExitExclusiveAccessToPreviousState();
}

bool Browser::IsWaitingForPointerLockPrompt(WebContents* web_contents) {
  return browser_window_features()
      ->exclusive_access_manager()
      ->pointer_lock_controller()
      ->IsWaitingForPointerLockPrompt(web_contents);
}

void Browser::RequestKeyboardLock(WebContents* web_contents,
                                  bool esc_key_locked) {
  browser_window_features()
      ->exclusive_access_manager()
      ->keyboard_lock_controller()
      ->RequestKeyboardLock(web_contents, esc_key_locked);
}

void Browser::CancelKeyboardLockRequest(WebContents* web_contents) {
  browser_window_features()
      ->exclusive_access_manager()
      ->keyboard_lock_controller()
      ->CancelKeyboardLockRequest(web_contents);
}

void Browser::RequestMediaAccessPermission(
    content::WebContents* web_contents,
    const content::MediaStreamRequest& request,
    content::MediaResponseCallback callback) {
  const extensions::Extension* extension =
      GetExtensionForOrigin(profile_, request.security_origin);
  MediaCaptureDevicesDispatcher::GetInstance()->ProcessMediaAccessRequest(
      web_contents, request, std::move(callback), extension);
}

void Browser::ProcessSelectAudioOutput(
    const content::SelectAudioOutputRequest& request,
    content::SelectAudioOutputCallback callback) {
#if defined(TOOLKIT_VIEWS)
  MediaCaptureDevicesDispatcher::GetInstance()->ProcessSelectAudioOutputRequest(
      this, request, std::move(callback));
#else
  std::move(callback).Run(
      base::unexpected(content::SelectAudioOutputError::kUnknown));
#endif
}

bool Browser::CheckMediaAccessPermission(
    content::RenderFrameHost* render_frame_host,
    const url::Origin& security_origin,
    blink::mojom::MediaStreamType type) {
  Profile* profile =
      Profile::FromBrowserContext(render_frame_host->GetBrowserContext());
  const extensions::Extension* extension =
      GetExtensionForOrigin(profile, security_origin.GetURL());
  return MediaCaptureDevicesDispatcher::GetInstance()
      ->CheckMediaAccessPermission(render_frame_host, security_origin, type,
                                   extension);
}

std::string Browser::GetTitleForMediaControls(WebContents* web_contents) {
  auto* const app_browser_controller = GetAppBrowserController();
  return app_browser_controller
             ? app_browser_controller->GetTitleForMediaControls()
             : std::string();
}

#if BUILDFLAG(ENABLE_PRINTING)
void Browser::PrintCrossProcessSubframe(
    content::WebContents* web_contents,
    const gfx::Rect& rect,
    int document_cookie,
    content::RenderFrameHost* subframe_host) const {
  auto* client = printing::PrintCompositeClient::FromWebContents(web_contents);
  if (client) {
    client->PrintCrossProcessSubframe(rect, document_cookie, subframe_host);
  }
}
#endif

#if BUILDFLAG(ENABLE_PAINT_PREVIEW)
void Browser::CapturePaintPreviewOfSubframe(
    content::WebContents* web_contents,
    const gfx::Rect& rect,
    const base::UnguessableToken& guid,
    content::RenderFrameHost* render_frame_host) {
  auto* client =
      paint_preview::PaintPreviewClient::FromWebContents(web_contents);
  if (client) {
    client->CaptureSubframePaintPreview(guid, rect, render_frame_host);
  }
}
#endif

///////////////////////////////////////////////////////////////////////////////
// Browser, web_modal::WebContentsModalDialogManagerDelegate implementation:

void Browser::SetWebContentsBlocked(content::WebContents* web_contents,
                                    bool blocked) {
  int index = tab_strip_model_->GetIndexOfWebContents(web_contents);
  if (index == TabStripModel::kNoTab) {
    // Removal of tabs from the TabStripModel can cause observer callbacks to
    // invoke this method. The WebContents may no longer exist in the
    // TabStripModel.
    // If the WebContents has a DevTools window,
    // the call is meant for the DevTools area.
    if (DevToolsWindow::AsDevToolsWindow(web_contents)) {
      window_->SetDevToolsScrimVisibility(blocked);
    }
    return;
  }

  // Drop HTML fullscreen to give users context for making informed decisions.
  // Skip browser-fullscreen, which is more expressly user-initiated.
  // Skip fullscreen-within-tab, which shows the browser frame.
  if (blocked && GetFullscreenState(web_contents).target_mode ==
                     content::FullscreenMode::kContent) {
    // Skip URLs with the automatic fullscreen content setting granted.
    const GURL& url = web_contents->GetLastCommittedURL();
    const HostContentSettingsMap* const content_settings =
        HostContentSettingsMapFactory::GetForProfile(
            web_contents->GetBrowserContext());
    if (content_settings->GetContentSetting(
            url, url, ContentSettingsType::AUTOMATIC_FULLSCREEN) !=
        CONTENT_SETTING_ALLOW) {
      web_contents->ExitFullscreen(true);
    }
  }

  tab_strip_model_->SetTabBlocked(index, blocked);

  const bool browser_active =
      GetLastActiveBrowserWindowInterfaceWithAnyProfile() == this;
  bool contents_is_active =
      tab_strip_model_->GetActiveWebContents() == web_contents;
  // If the WebContents is foremost (the active tab in the front-most browser)
  // and is being unblocked, focus it to make sure that input works again.
  if (!blocked && contents_is_active && browser_active) {
    web_contents->Focus();
  }
}

web_modal::WebContentsModalDialogHost* Browser::GetWebContentsModalDialogHost(
    content::WebContents* web_contents) {
  return window_->GetWebContentsModalDialogHostFor(web_contents);
}

///////////////////////////////////////////////////////////////////////////////
// Browser, BookmarkTabHelperObserver implementation:

void Browser::URLStarredChanged(content::WebContents* web_contents,
                                bool starred) {
  if (web_contents == tab_strip_model_->GetActiveWebContents()) {
    window_->SetStarredState(starred);
  }
}

///////////////////////////////////////////////////////////////////////////////
// Browser, ZoomObserver implementation:

void Browser::OnZoomControllerDestroyed(zoom::ZoomController* zoom_controller) {
  // SetAsDelegate() takes care of removing the observers.
}

void Browser::OnZoomChanged(
    const zoom::ZoomController::ZoomChangedEventData& data) {
  if (data.web_contents == tab_strip_model_->GetActiveWebContents()) {
    window_->ZoomChangedForActiveTab(data.can_show_bubble);
    // Change the zoom commands state based on the zoom state
    GetCommandController()->ZoomStateChanged();
  }
}

///////////////////////////////////////////////////////////////////////////////
// Browser, ThemeServiceObserver implementation:

void Browser::OnThemeChanged() {
  window()->UserChangedTheme(BrowserThemeChangeType::kBrowserTheme);
}

///////////////////////////////////////////////////////////////////////////////
// Browser, Command and state updating (private):

void Browser::OnTabInsertedAt(WebContents* contents, int index) {
  // If this Browser is about to be deleted, then WebContents should not be
  // added to it. This is because scheduling the delete can not be undone, and
  // proper cleanup is not done if a WebContents is added once delete it
  // scheduled (WebContents is leaked, unload handlers aren't checked...).
  // TODO(crbug.com/40064092): this should check that `is_delete_scheduled_` is
  // false.
  DUMP_WILL_BE_CHECK(!is_delete_scheduled_);

  SetAsDelegate(contents, true);

  sessions::SessionTabHelper::FromWebContents(contents)->SetWindowID(
      session_id());

  SyncHistoryWithTabs(index);

  // Make sure the loading state is updated correctly, otherwise the throbber
  // won't start if the page is loading. Note that we don't want to
  // ScheduleUIUpdate() because the tab may not have been inserted in the UI
  // yet if this function is called before TabStripModel::TabInsertedAt().
  UpdateWindowForLoadingStateChanged(contents, true);

  SessionServiceBase* service = GetAppropriateSessionServiceForProfile(this);

  if (service) {
    service->TabInserted(contents);
    int new_active_index = tab_strip_model_->active_index();
    if (index < new_active_index) {
      service->SetSelectedTabInWindow(session_id(), new_active_index);
    }
  }
}

void Browser::OnTabClosing(WebContents* contents) {
  // When this function is called |contents| has been removed from the
  // TabStripModel. Some of the following code may trigger calling to the
  // WebContentsDelegate, which is |this|, which may try to look for the
  // WebContents in the TabStripModel, and fail because the WebContents has
  // been removed. To avoid these problems the delegate is reset now.
  SetAsDelegate(contents, false);

  // Typically, ModalDialogs are closed when the WebContents is destroyed.
  // However, when the tab is being closed, we must first close the dialogs [to
  // give them an opportunity to clean up after themselves] while the state
  // associated with their tab is still valid.
  WebContentsModalDialogManager::FromWebContents(contents)->CloseAllDialogs();

  // Page load metrics need to be informed that the WebContents will soon be
  // destroyed, so that upcoming visibility changes can be ignored.
  page_load_metrics::MetricsWebContentsObserver* metrics_observer =
      page_load_metrics::MetricsWebContentsObserver::FromWebContents(contents);
  metrics_observer->WebContentsWillSoonBeDestroyed();

  browser_window_features()->exclusive_access_manager()->OnTabClosing(contents);
  SessionServiceBase* service = GetAppropriateSessionServiceForProfile(this);

  if (service) {
    service->TabClosing(contents);
  }
}

void Browser::OnTabDetached(WebContents* contents, bool was_active) {
  if (!tab_strip_model_->closing_all()) {
    SessionServiceBase* service = GetAppropriateSessionServiceIfExisting(this);
    if (service) {
      service->SetSelectedTabInWindow(session_id(),
                                      tab_strip_model_->active_index());
    }
  }

  TabDetachedAtImpl(contents, was_active, DetachType::kDetach);

  window_->OnTabDetached(contents, was_active);
}

void Browser::OnTabDeactivated(WebContents* contents) {
  browser_window_features()->exclusive_access_manager()->OnTabDeactivated(
      contents);
  SearchTabHelper::FromWebContents(contents)->OnTabDeactivated();

  // Save what the user's currently typing, so it can be restored when we
  // switch back to this tab.
  window_->GetLocationBar()->SaveStateToContents(contents);
}

void Browser::OnActiveTabChanged(WebContents* old_contents,
                                 WebContents* new_contents,
                                 int index,
                                 int reason) {
  TRACE_EVENT0("ui", "Browser::OnActiveTabChanged");
// Mac correctly sets the initial background color of new tabs to the theme
// background color, so it does not need this block of code. Aura should
// implement this as well.
// https://crbug.com/719230
#if !BUILDFLAG(IS_MAC)
  // Copies the background color from an old WebContents to a new one that
  // replaces it on the screen. This allows the new WebContents to use the
  // old one's background color as the starting background color, before having
  // loaded any contents. As a result, we avoid flashing white when moving to
  // a new tab. (There is also code in RenderFrameHostManager to do something
  // similar for intra-tab navigations.)
  if (old_contents && new_contents) {
    // While GetPrimaryMainFrame() is guaranteed to return non-null, GetView()
    // is not, e.g. between WebContents creation and creation of the
    // RenderWidgetHostView.
    RenderWidgetHostView* old_view =
        old_contents->GetPrimaryMainFrame()->GetView();
    RenderWidgetHostView* new_view =
        new_contents->GetPrimaryMainFrame()->GetView();
    if (old_view && new_view) {
      new_view->CopyBackgroundColorIfPresentFrom(*old_view);
    }
  }
#endif

  base::RecordAction(UserMetricsAction("ActiveTabChanged"));

  // Update the bookmark state, since the BrowserWindow may query it during
  // OnActiveTabChanged() below.
  BookmarkBarController::From(this)->UpdateBookmarkBarState(
      BookmarkBarController::StateChangeReason::kTabSwitch);

  // Let the BrowserWindow do its handling.  On e.g. views this changes the
  // focused object, which should happen before we update the toolbar below,
  // since the omnibox expects the correct element to already be focused when
  // it is updated.
  window_->OnActiveTabChanged(old_contents, new_contents, index, reason);

  browser_window_features()->exclusive_access_manager()->OnTabDetachedFromView(
      old_contents);

  // If we have any update pending, do it now.
  if (chrome_updater_factory_.HasWeakPtrs() && old_contents) {
    ProcessPendingUIUpdates();
  }

  // Propagate the profile to the location bar.
  UpdateToolbar((reason & CHANGE_REASON_REPLACED) == 0);

  // Update reload/stop state.
  chrome::BrowserCommandController* const browser_command_controller =
      GetCommandController();
  browser_command_controller->LoadingStateChanged(new_contents->IsLoading(),
                                                  true);

  // Update commands to reflect current state.
  browser_command_controller->TabStateChanged();

  // Reset the status bubble.
  std::vector<StatusBubble*> status_bubbles = GetStatusBubbles();
  for (StatusBubble* status_bubble : status_bubbles) {
    status_bubble->Hide();

    // Show the loading state (if any).
    if (status_bubble == status_bubbles.front()) {
      status_bubble->SetStatus(CoreTabHelper::FromWebContents(
                                   tab_strip_model_->GetActiveWebContents())
                                   ->GetStatusText());
    }
  }

  if (HasFindBarController()) {
    CreateOrGetFindBarController()->HandleActiveTabChanged(new_contents);
  }

  // Update sessions (selected tab index and last active time). Don't force
  // creation of sessions. If sessions doesn't exist, the change will be picked
  // up by sessions when created.
  SessionServiceBase* service = GetAppropriateSessionServiceIfExisting(this);
  if (service && !tab_strip_model_->closing_all()) {
    service->SetSelectedTabInWindow(session_id(),
                                    tab_strip_model_->active_index());
    service->SetLastActiveTime(
        session_id(), sessions::SessionTabHelper::IdForTab(new_contents),
        base::Time::Now());
  }

  SearchTabHelper::FromWebContents(new_contents)->OnTabActivated();
  did_active_tab_change_callback_list_.Notify(this);
}

void Browser::OnTabMoved(int from_index, int to_index) {
  DCHECK(from_index >= 0 && to_index >= 0);
  // Notify the history service.
  SyncHistoryWithTabs(std::min(from_index, to_index));
}

void Browser::OnTabReplacedAt(WebContents* old_contents,
                              WebContents* new_contents,
                              int index) {
  bool was_active = index == tab_strip_model_->active_index();
  if (was_active) {
    did_active_tab_change_callback_list_.Notify(this);
  }
  TabDetachedAtImpl(old_contents, was_active, DetachType::kReplace);
  browser_window_features()->exclusive_access_manager()->OnTabClosing(
      old_contents);
  SessionServiceBase* session_service =
      GetAppropriateSessionServiceForProfile(this);
  if (session_service) {
    session_service->TabClosing(old_contents);
  }
  OnTabInsertedAt(new_contents, index);

  if (!new_contents->GetController().IsInitialBlankNavigation()) {
    // Send out notification so that observers are updated appropriately.
    int entry_count = new_contents->GetController().GetEntryCount();
    new_contents->GetController().NotifyEntryChanged(
        new_contents->GetController().GetEntryAtIndex(entry_count - 1));
  }

  if (session_service) {
    // The new_contents may end up with a different navigation stack. Force
    // the session service to update itself.
    session_service->TabRestored(new_contents,
                                 tab_strip_model_->IsTabPinned(index));
  }
}

void Browser::OnDevToolsAvailabilityChanged() {
  for (auto& agent_host : content::DevToolsAgentHost::GetAll()) {
    if (!DevToolsWindow::AllowDevToolsFor(profile_,
                                          agent_host->GetWebContents())) {
      agent_host->ForceDetachAllSessions();
    }
  }
}

///////////////////////////////////////////////////////////////////////////////
// Browser, UI update coalescing and handling (private):

void Browser::UpdateToolbar(bool should_restore_state) {
  TRACE_EVENT0("ui", "Browser::UpdateToolbar");
  window_->UpdateToolbar(should_restore_state
                             ? tab_strip_model_->GetActiveWebContents()
                             : nullptr);
}

void Browser::UpdateToolbarSecurityState() {
  TRACE_EVENT0("ui", "Browser::UpdateToolbarSecurityState");
  window_->UpdateToolbarSecurityState();
}

void Browser::ScheduleUIUpdate(WebContents* source, unsigned changed_flags) {
  DCHECK(source);
  // WebContents may in some rare cases send updates after they've been detached
  // from the tabstrip but before they are deleted, causing a potential crash if
  // we proceed. For now bail out.
  // TODO(crbug.com/40100269) Figure out a safe way to detach browser delegate
  // from WebContents when it's removed so this doesn't happen - then put a
  // DCHECK back here.
  if (tab_strip_model_->GetIndexOfWebContents(source) ==
      TabStripModel::kNoTab) {
    return;
  }

  // Do some synchronous updates.
  if (changed_flags & content::INVALIDATE_TYPE_URL) {
    if (source == tab_strip_model_->GetActiveWebContents()) {
      // Only update the URL for the current tab. Note that we do not update
      // the navigation commands since those would have already been updated
      // synchronously by NavigationStateChanged.
      UpdateToolbar(false);
    } else {
      // Clear the saved tab state for the tab that navigated, so that we don't
      // restore any user text after the old URL has been invalidated (e.g.,
      // after a new navigation commits in that tab while unfocused).
      window_->ResetToolbarTabState(source);
    }
    changed_flags &= ~content::INVALIDATE_TYPE_URL;
  }

  if (changed_flags & content::INVALIDATE_TYPE_LOAD) {
    // Update the loading state synchronously. This is so the throbber will
    // immediately start/stop, which gives a more snappy feel. We want to do
    // this for any tab so they start & stop quickly.
    tab_strip_model_->UpdateWebContentsStateAt(
        tab_strip_model_->GetIndexOfWebContents(source),
        TabChangeType::kLoadingOnly);
    // The status bubble needs to be updated during INVALIDATE_TYPE_LOAD too,
    // but we do that asynchronously by not stripping INVALIDATE_TYPE_LOAD from
    // changed_flags.
  }

  // If the only updates were synchronously handled above, we're done.
  if (changed_flags == 0) {
    return;
  }

  // Save the dirty bits.
  scheduled_updates_[source] |= changed_flags;

  if (!chrome_updater_factory_.HasWeakPtrs()) {
    base::TimeDelta delay = update_ui_immediately_for_testing_
                                ? base::Milliseconds(0)
                                : kUIUpdateCoalescingTime;
    // No task currently scheduled, start another.
    base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
        FROM_HERE,
        base::BindOnce(&Browser::ProcessPendingUIUpdates,
                       chrome_updater_factory_.GetWeakPtr()),
        delay);
  }
}

void Browser::ProcessPendingUIUpdates() {
#ifndef NDEBUG
  // Validate that all tabs we have pending updates for exist. This is scary
  // because the pending list must be kept in sync with any detached or
  // deleted tabs.
  for (UpdateMap::const_iterator i = scheduled_updates_.begin();
       i != scheduled_updates_.end(); ++i) {
    bool found = false;
    for (int tab = 0; tab < tab_strip_model_->count(); tab++) {
      if (tab_strip_model_->GetWebContentsAt(tab) == i->first) {
        found = true;
        break;
      }
    }
    DCHECK(found);
  }
#endif

  chrome_updater_factory_.InvalidateWeakPtrs();

  for (UpdateMap::const_iterator i = scheduled_updates_.begin();
       i != scheduled_updates_.end(); ++i) {
    // Do not dereference |contents|, it may be out-of-date!
    const WebContents* contents = i->first;
    unsigned flags = i->second;

    if (contents == tab_strip_model_->GetActiveWebContents()) {
      // Updates that only matter when the tab is selected go here.

      // Updating the URL happens synchronously in ScheduleUIUpdate.
      std::vector<StatusBubble*> status_bubbles = GetStatusBubbles();
      if (flags & content::INVALIDATE_TYPE_LOAD && status_bubbles.size() > 0) {
        status_bubbles.front()->SetStatus(
            CoreTabHelper::FromWebContents(
                tab_strip_model_->GetActiveWebContents())
                ->GetStatusText());
      }

      if (flags &
          (content::INVALIDATE_TYPE_TAB | content::INVALIDATE_TYPE_TITLE)) {
        window_->UpdateTitleBar();
      }
    }

    // Updates that don't depend upon the selected state go here.
    if (flags & (content::INVALIDATE_TYPE_TAB | content::INVALIDATE_TYPE_TITLE |
                 content::INVALIDATE_TYPE_AUDIO)) {
      tab_strip_model_->UpdateWebContentsStateAt(
          tab_strip_model_->GetIndexOfWebContents(contents),
          TabChangeType::kAll);
    }

    // Update the bookmark bar and PWA install icon. It may happen that the tab
    // is crashed, and if so, the bookmark bar and PWA install icon should be
    // hidden.
    if (flags & content::INVALIDATE_TYPE_TAB) {
      // Update bookmark bar state with kTabState to handle tab state changes
      // (like crashes). This is different from kTabSwitch which is already
      // handled in Browser::OnActiveTabChanged().
      BookmarkBarController::From(this)->UpdateBookmarkBarState(
          BookmarkBarController::StateChangeReason::kTabState);

      // TODO(crbug.com/40122780): Ideally, we should simply ask the state to
      // update, and doing that in an appropriate and efficient manner.
      window()->UpdatePageActionIcon(PageActionIconType::kPwaInstall);
    }

    // We don't need to process INVALIDATE_STATE, since that's not visible.
  }

  scheduled_updates_.clear();
}

void Browser::RemoveScheduledUpdatesFor(WebContents* contents) {
  if (!contents) {
    return;
  }

  auto i = scheduled_updates_.find(contents);
  if (i != scheduled_updates_.end()) {
    scheduled_updates_.erase(i);
  }
}

void Browser::OnFileSelectedFromDialog(const GURL& url) {
  OpenURL(OpenURLParams(url, Referrer(), WindowOpenDisposition::CURRENT_TAB,
                        ui::PAGE_TRANSITION_TYPED, false),
          /*navigation_handle_callback=*/{});
}

///////////////////////////////////////////////////////////////////////////////
// Browser, Getters for UI (private):

std::vector<StatusBubble*> Browser::GetStatusBubbles() {
  // For kiosk and exclusive app mode we want to always hide the status bubble.
  if (IsRunningInAppMode()) {
    return {};
  }

  // We hide the status bar for web apps windows as this matches native
  // experience. However, we include the status bar for 'minimal-ui' display
  // mode, as the minimal browser UI includes the status bar.
  auto* const app_browser_controller = GetAppBrowserController();
  if (app_browser_controller &&
      !app_browser_controller->HasMinimalUiButtons()) {
    return {};
  }

  if (window_) {
    return window_->GetStatusBubbles();
  } else {
    return {};
  }
}

chrome::BrowserCommandController* Browser::GetCommandController() {
  return GetFeatures().browser_command_controller();
}

///////////////////////////////////////////////////////////////////////////////
// Browser, Session restore functions (private):

void Browser::SyncHistoryWithTabs(int index) {
  SessionServiceBase* service = GetAppropriateSessionServiceForProfile(this);

  SessionService* session_service =
      SessionServiceFactory::GetForProfileIfExisting(profile());

  if (!service && !session_service) {
    return;
  }

  for (int i = index; i < tab_strip_model_->count(); ++i) {
    WebContents* web_contents = tab_strip_model_->GetWebContentsAt(i);
    if (web_contents) {
      SessionID tab_id = sessions::SessionTabHelper::IdForTab(web_contents);
      if (service) {
        service->SetPinnedState(session_id(), tab_id,
                                tab_strip_model_->IsTabPinned(i));
      }

      if (!IsRelevantToAppSessionService(type_) && session_service) {
        session_service->SetTabIndexInWindow(session_id(), tab_id, i);

        std::optional<tab_groups::TabGroupId> group_id =
            tab_strip_model_->GetTabGroupForTab(i);
        session_service->SetTabGroup(session_id(), tab_id, std::move(group_id));
      }
    }
  }
}

///////////////////////////////////////////////////////////////////////////////
// Browser, In-progress download termination handling (private):

bool Browser::CanCloseWithInProgressDownloads() {
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS)
  // On Mac and ChromeOS, non-incognito and non-Guest downloads can still
  // continue after window is closed.
  if (!profile_->IsOffTheRecord()) {
    return true;
  }
#endif

  // If we've prompted, we need to hear from the user before we
  // can close.
  if (cancel_download_confirmation_state_ !=
      CancelDownloadConfirmationState::kNotPrompted) {
    return cancel_download_confirmation_state_ !=
           CancelDownloadConfirmationState::kWaitingForResponse;
  }

  int num_downloads_blocking;
  DownloadCloseType dialog_type =
      OkToCloseWithInProgressDownloads(&num_downloads_blocking);
  if (dialog_type == DownloadCloseType::kOk) {
    return true;
  }

  // Closing this window will kill some downloads; prompt to make sure
  // that's ok.
  cancel_download_confirmation_state_ =
      CancelDownloadConfirmationState::kWaitingForResponse;
  window_->ConfirmBrowserCloseWithPendingDownloads(
      num_downloads_blocking, dialog_type,
      base::BindOnce(&Browser::InProgressDownloadResponse,
                     weak_factory_.GetWeakPtr()));

  // Return false so the browser does not close.  We'll close if the user
  // confirms in the dialog.
  return false;
}

void Browser::InProgressDownloadResponse(bool cancel_downloads) {
  if (cancel_downloads) {
    cancel_download_confirmation_state_ =
        CancelDownloadConfirmationState::kResponseReceived;

    if (ShouldShowCookieMigrationNoticeForBrowser(*this)) {
      ShowCookieClearOnExitMigrationNotice(
          *this, base::BindOnce(&Browser::CookieMigrationNoticeResponse,
                                weak_factory_.GetWeakPtr()));
    } else {
      std::move(warn_before_closing_callback_)
          .Run(WarnBeforeClosingResult::kOkToClose);
    }
    return;
  }

  // Sets the confirmation state to
  // CancelDownloadConfirmationState::kNotPrompted so that if the user tries to
  // close again we'll show the warning again.
  cancel_download_confirmation_state_ =
      CancelDownloadConfirmationState::kNotPrompted;

  // Show the download page so the user can figure-out what downloads are still
  // in-progress.
  chrome::ShowDownloads(this);

  std::move(warn_before_closing_callback_)
      .Run(WarnBeforeClosingResult::kDoNotClose);
}

void Browser::CookieMigrationNoticeResponse(bool proceed_closing) {
  std::move(warn_before_closing_callback_)
      .Run(proceed_closing ? WarnBeforeClosingResult::kOkToClose
                           : WarnBeforeClosingResult::kDoNotClose);
}

void Browser::FinishWarnBeforeClosing(WarnBeforeClosingResult result) {
  switch (result) {
    case WarnBeforeClosingResult::kOkToClose:
      chrome::CloseWindow(this);
      break;
    case WarnBeforeClosingResult::kDoNotClose:
      // Reset UnloadController::is_attempting_to_close_browser_ so that we
      // don't prompt every time any tab is closed. http://crbug.com/305516
      unload_controller_.CancelWindowClose();
  }
}

///////////////////////////////////////////////////////////////////////////////
// Browser, Assorted utility functions (private):

void Browser::SetAsDelegate(WebContents* web_contents, bool set_delegate) {
  Browser* delegate = set_delegate ? this : nullptr;

  // WebContents...
  web_contents->SetDelegate(delegate);

  // ...and all the helpers.
  WebContentsModalDialogManager::FromWebContents(web_contents)
      ->SetDelegate(delegate);
  zoom::ZoomController* zoom_controller =
      zoom::ZoomController::FromWebContents(web_contents);
  if (delegate) {
    zoom_controller->AddObserver(this);
    BookmarkTabHelper::FromWebContents(web_contents)->AddObserver(this);
    web_contents_collection_.StartObserving(web_contents);
  } else {
    zoom_controller->RemoveObserver(this);
    BookmarkTabHelper::FromWebContents(web_contents)->RemoveObserver(this);
    web_contents_collection_.StopObserving(web_contents);
  }
}

void Browser::TabDetachedAtImpl(content::WebContents* contents,
                                bool was_active,
                                DetachType type) {
  if (type == DetachType::kDetach) {
    // Save the current location bar state, but only if the tab being detached
    // is the selected tab.  Because saving state can conditionally revert the
    // location bar, saving the current tab's location bar state to a
    // non-selected tab can corrupt both tabs.
    if (was_active) {
      LocationBar* location_bar = window()->GetLocationBar();
      if (location_bar) {
        location_bar->SaveStateToContents(contents);
      }
    }

    if (!tab_strip_model_->closing_all()) {
      SyncHistoryWithTabs(0);
    }
  }

  SetAsDelegate(contents, false);
  RemoveScheduledUpdatesFor(contents);

  if (HasFindBarController() && was_active) {
    CreateOrGetFindBarController()->ChangeWebContents(nullptr);
  }
}

void Browser::UpdateWindowForLoadingStateChanged(content::WebContents* source,
                                                 bool should_show_loading_ui) {
  window_->UpdateLoadingAnimations(/* is_visible=*/!window_->IsMinimized());
  window_->UpdateTitleBar();

  WebContents* selected_contents = tab_strip_model_->GetActiveWebContents();
  if (source == selected_contents) {
    bool is_loading = source->IsLoading() && should_show_loading_ui;
    GetCommandController()->LoadingStateChanged(is_loading, false);

    std::vector<StatusBubble*> status_bubbles = GetStatusBubbles();
    if (status_bubbles.size() > 0) {
      status_bubbles.front()->SetStatus(
          CoreTabHelper::FromWebContents(selected_contents)->GetStatusText());
    }
  }
}

bool Browser::NormalBrowserSupportsWindowFeature(WindowFeature feature,
                                                 bool check_can_support) const {
  const base::FunctionRef<bool(const Browser*)> fullscreen =
      MaybeLazyIsFullscreen(this);
  switch (feature) {
    case WindowFeature::kFeatureBookmarkBar:
      return true;
    case WindowFeature::kFeatureTabStrip:
    case WindowFeature::kFeatureToolbar:
    case WindowFeature::kFeatureLocationBar:
      return check_can_support || !fullscreen(this);
    case WindowFeature::kFeatureTitleBar:
    case WindowFeature::kFeatureNone:
      return false;
  }
}

bool Browser::PopupBrowserSupportsWindowFeature(WindowFeature feature,
                                                bool check_can_support) const {
  const base::FunctionRef<bool(const Browser*)> fullscreen =
      MaybeLazyIsFullscreen(this);
  switch (feature) {
    case WindowFeature::kFeatureTitleBar:
    case WindowFeature::kFeatureLocationBar:
      return check_can_support || (!fullscreen(this) && !is_trusted_source());
    case WindowFeature::kFeatureTabStrip:
    case WindowFeature::kFeatureToolbar:
    case WindowFeature::kFeatureBookmarkBar:
    case WindowFeature::kFeatureNone:
      return false;
  }
}

bool Browser::AppPopupBrowserSupportsWindowFeature(
    WindowFeature feature,
    bool check_can_support) const {
  const base::FunctionRef<bool(const Browser*)> fullscreen =
      MaybeLazyIsFullscreen(this);
  switch (feature) {
    case WindowFeature::kFeatureTitleBar:
      return check_can_support || !fullscreen(this);
    case WindowFeature::kFeatureLocationBar:
      return GetAppBrowserController() &&
             (check_can_support || !fullscreen(this));
    default:
      return PopupBrowserSupportsWindowFeature(feature, check_can_support);
  }
}

bool Browser::AppBrowserSupportsWindowFeature(WindowFeature feature,
                                              bool check_can_support) const {
  auto* const app_browser_controller = GetAppBrowserController();
  DCHECK(app_browser_controller);
  const base::FunctionRef<bool(const Browser*)> fullscreen =
      MaybeLazyIsFullscreen(this);
  switch (feature) {
    // Web apps should always support the toolbar, so the title/origin of the
    // current page can be shown when browsing a url that is not inside the app.
    // Note: Final determination of whether or not the toolbar is shown is made
    // by the |AppBrowserController|.
    // TODO(crbug.com/40639933): Make this control the visibility of Browser
    // Controls more generally.
    case WindowFeature::kFeatureToolbar:
      return true;
    case WindowFeature::kFeatureTitleBar:
    // TODO(crbug.com/40639933): Make this control the visibility of
    // CustomTabBarView.
    case WindowFeature::kFeatureLocationBar:
      return check_can_support || !fullscreen(this);
    case WindowFeature::kFeatureTabStrip:
      // Even when the app has a tab strip, it should be hidden in
      // fullscreen. This is consistent with the behavior of
      // NormalBrowserSupportsWindowFeature().
      return app_browser_controller->has_tab_strip() &&
             (check_can_support || !fullscreen(this));
    case WindowFeature::kFeatureBookmarkBar:
    case WindowFeature::kFeatureNone:
      return false;
  }
}

#if BUILDFLAG(IS_CHROMEOS)
// TODO(b/64863368): Consider Fullscreen mode.
bool Browser::CustomTabBrowserSupportsWindowFeature(
    WindowFeature feature) const {
  switch (feature) {
    case WindowFeature::kFeatureToolbar:
      return true;
    case WindowFeature::kFeatureTitleBar:
    case WindowFeature::kFeatureLocationBar:
    case WindowFeature::kFeatureTabStrip:
    case WindowFeature::kFeatureBookmarkBar:
    case WindowFeature::kFeatureNone:
      return false;
  }
}
#endif

bool Browser::PictureInPictureBrowserSupportsWindowFeature(
    WindowFeature feature,
    bool check_can_support) const {
  switch (feature) {
    case WindowFeature::kFeatureTitleBar:
      return true;
    case WindowFeature::kFeatureLocationBar:
    case WindowFeature::kFeatureTabStrip:
    case WindowFeature::kFeatureToolbar:
    case WindowFeature::kFeatureBookmarkBar:
    case WindowFeature::kFeatureNone:
      return false;
  }
}

bool Browser::SupportsWindowFeatureImpl(WindowFeature feature,
                                        bool check_can_support) const {
  switch (type_) {
    case TYPE_NORMAL:
      return NormalBrowserSupportsWindowFeature(feature, check_can_support);
    case TYPE_POPUP:
      return PopupBrowserSupportsWindowFeature(feature, check_can_support);
    case TYPE_APP:
      if (GetAppBrowserController()) {
        return AppBrowserSupportsWindowFeature(feature, check_can_support);
      }
      // TODO(crbug.com/40639933): Change legacy apps to TYPE_APP_POPUP.
      return AppPopupBrowserSupportsWindowFeature(feature, check_can_support);
    case TYPE_DEVTOOLS:
    case TYPE_APP_POPUP:
      return AppPopupBrowserSupportsWindowFeature(feature, check_can_support);
#if BUILDFLAG(IS_CHROMEOS)
    case TYPE_CUSTOM_TAB:
      return CustomTabBrowserSupportsWindowFeature(feature);
#endif
    case TYPE_PICTURE_IN_PICTURE:
      return PictureInPictureBrowserSupportsWindowFeature(feature,
                                                          check_can_support);
  }
}

bool Browser::IsBrowserClosing() const {
  BrowserList* browser_list = BrowserList::GetInstance();
  const bool removed_from_browserlist =
      is_initialized_ &&
      std::ranges::find_if(*browser_list, [this](Browser* browser) {
        return browser == this;
      }) == browser_list->end();

  const BrowserList::BrowserSet& closing_browsers =
      browser_list->currently_closing_browsers();

  return base::Contains(closing_browsers, this) || removed_from_browserlist;
}

bool Browser::ShouldCreateBackgroundContents(
    content::SiteInstance* source_site_instance,
    const GURL& opener_url,
    const std::string& frame_name) {
  extensions::ExtensionSystem* extension_system =
      extensions::ExtensionSystem::Get(profile_);

  if (!opener_url.is_valid() || frame_name.empty() ||
      !extension_system->is_ready()) {
    return false;
  }

  // Only hosted apps have web extents, so this ensures that only hosted apps
  // can create BackgroundContents. We don't have to check for background
  // permission as that is checked in RenderMessageFilter when the CreateWindow
  // message is processed.
  const Extension* extension = extensions::ExtensionRegistry::Get(profile_)
                                   ->enabled_extensions()
                                   .GetHostedAppByURL(opener_url);
  if (!extension) {
    return false;
  }

  // No BackgroundContents allowed if BackgroundContentsService doesn't exist.
  BackgroundContentsService* service =
      BackgroundContentsServiceFactory::GetForProfile(profile_);
  if (!service) {
    return false;
  }

  // Ensure that we're trying to open this from the extension's process.
  extensions::ProcessMap* process_map = extensions::ProcessMap::Get(profile_);
  if (!source_site_instance->HasProcess() ||
      !process_map->Contains(
          extension->id(),
          source_site_instance->GetProcess()->GetDeprecatedID())) {
    return false;
  }

  return true;
}

BackgroundContents* Browser::CreateBackgroundContents(
    content::SiteInstance* source_site_instance,
    content::RenderFrameHost* opener,
    const GURL& opener_url,
    bool is_new_browsing_instance,
    const std::string& frame_name,
    const GURL& target_url,
    const content::StoragePartitionConfig& partition_config,
    content::SessionStorageNamespace* session_storage_namespace) {
  BackgroundContentsService* service =
      BackgroundContentsServiceFactory::GetForProfile(profile_);
  const Extension* extension = extensions::ExtensionRegistry::Get(profile_)
                                   ->enabled_extensions()
                                   .GetHostedAppByURL(opener_url);
  bool allow_js_access = extensions::BackgroundInfo::AllowJSAccess(extension);
  // Only allow a single background contents per app.
  BackgroundContents* existing =
      service->GetAppBackgroundContents(extension->id());
  if (existing) {
    // For non-scriptable background contents, ignore the request altogether,
    // Note that ShouldCreateBackgroundContents() returning true will also
    // suppress creation of the normal WebContents.
    if (!allow_js_access) {
      return nullptr;
    }
    // For scriptable background pages, if one already exists, close it (even
    // if it was specified in the manifest).
    service->DeleteBackgroundContents(existing);
  }

  // Passed all the checks, so this should be created as a BackgroundContents.
  if (allow_js_access) {
    return service->CreateBackgroundContents(
        source_site_instance, opener, is_new_browsing_instance, frame_name,
        extension->id(), partition_config, session_storage_namespace);
  }

  // If script access is not allowed, create the the background contents in a
  // new SiteInstance, so that a separate process is used. We must not use any
  // of the passed-in routing IDs, as they are objects in the opener's
  // process.
  BackgroundContents* contents = service->CreateBackgroundContents(
      content::SiteInstance::Create(source_site_instance->GetBrowserContext()),
      nullptr, is_new_browsing_instance, frame_name, extension->id(),
      partition_config, session_storage_namespace);

  // When a separate process is used, the original renderer cannot access the
  // new window later, thus we need to navigate the window now.
  contents->web_contents()->GetController().LoadURL(
      target_url, content::Referrer(), ui::PAGE_TRANSITION_LINK,
      std::string());  // No extra headers.

  return contents;
}

FindBarController* Browser::CreateOrGetFindBarController() {
  return GetFeatures().GetFindBarController();
}

bool Browser::HasFindBarController() {
  return GetFeatures().HasFindBarController();
}

Browser::ScopedWindowCallToActionImpl::ScopedWindowCallToActionImpl(
    Browser* browser)
    : browser_(browser->weak_factory_.GetWeakPtr()) {
  DCHECK(!browser_->showing_call_to_action_);
  browser_->showing_call_to_action_ = true;
}

Browser::ScopedWindowCallToActionImpl::~ScopedWindowCallToActionImpl() {
  browser_->showing_call_to_action_ = false;
}
