// 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/unload_controller.h"

#include <algorithm>

#include "base/functional/bind.h"
#include "base/location.h"
#include "base/task/single_thread_task_runner.h"
#include "chrome/browser/devtools/devtools_window.h"
#include "chrome/browser/lifetime/application_lifetime_desktop.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/tabs/tab_group_model.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/tabs/tab_strip_model_delegate.h"
#include "chrome/browser/ui/web_applications/app_browser_controller.h"
#include "chrome/browser/ui/web_applications/web_app_tabbed_utils.h"
#include "chrome/browser/web_applications/policy/web_app_policy_manager.h"
#include "chrome/browser/web_applications/web_app_provider.h"
#include "components/performance_manager/public/execution_context_priority/execution_context_priority.h"
#include "components/tab_groups/tab_group_id.h"
#include "components/tabs/public/tab_group.h"
#include "components/webapps/common/web_app_id.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "extensions/buildflags/buildflags.h"

#if BUILDFLAG(ENABLE_EXTENSIONS)
#include "chrome/browser/profiles/profile.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/constants.h"
#endif  // (ENABLE_EXTENSIONS)

#if BUILDFLAG(IS_CHROMEOS)
#include "chrome/browser/ash/boca/on_task/on_task_locked_controller.h"
#endif  // BUILDFLAG(IS_CHROMEOS)

////////////////////////////////////////////////////////////////////////////////
// UnloadController, public:

UnloadController::UnloadController(Browser* browser)
    : browser_(browser),
      web_contents_collection_(this),
      is_attempting_to_close_browser_(false) {
  browser_->tab_strip_model()->AddObserver(this);
}

UnloadController::~UnloadController() {
  browser_->tab_strip_model()->RemoveObserver(this);
}

bool UnloadController::CanCloseContents(content::WebContents* contents) {
  // Don't try to close the tab when the whole browser is being closed, since
  // that avoids the fast shutdown path where we just kill all the renderers.
  if (is_attempting_to_close_browser_) {
    ClearUnloadState(contents, true);
  }

  if (!web_app::IsTabClosable(
          browser_->tab_strip_model(),
          browser_->tab_strip_model()->GetIndexOfWebContents(contents))) {
    return false;
  }

#if BUILDFLAG(IS_CHROMEOS)
  // Tabs cannot be closed when the app is locked for OnTask. Only relevant for
  // non-web browser scenarios.
  if (ash::boca::OnTaskLockedController::From(browser_)
          ->is_locked_for_on_task()) {
    return false;
  }
#endif

  return !is_attempting_to_close_browser_ ||
         is_calling_before_unload_handlers();
}

bool UnloadController::ShouldRunUnloadEventsHelper(
    content::WebContents* contents) {
  // If |contents| is being inspected, devtools needs to intercept beforeunload
  // events.
  return DevToolsWindow::GetInstanceForInspectedWebContents(contents) !=
         nullptr;
}

bool UnloadController::RunUnloadEventsHelper(content::WebContents* contents) {
#if BUILDFLAG(ENABLE_EXTENSIONS)
  // Don't run for extensions that are disabled or uninstalled; the tabs will
  // be killed if they make any network requests, and the extension shouldn't
  // be doing any work if it's removed.
  GURL url = contents->GetLastCommittedURL();
  if (url.SchemeIs(extensions::kExtensionScheme) &&
      !extensions::ExtensionRegistry::Get(browser_->profile())
           ->enabled_extensions()
           .GetExtensionOrAppByURL(url)) {
    return false;
  }
#endif  // (ENABLE_EXTENSIONS)

  // Special case for when we quit an application. The devtools window can
  // close if it's beforeunload event has already fired which will happen due
  // to the interception of it's content's beforeunload.
  if (browser_->is_type_devtools() &&
      DevToolsWindow::HasFiredBeforeUnloadEventForDevToolsBrowser(browser_)) {
    return false;
  }

  // If there's a devtools window attached to |contents|,
  // we would like devtools to call its own beforeunload handlers first,
  // and then call beforeunload handlers for |contents|.
  // See DevToolsWindow::InterceptPageBeforeUnload for details.
  if (DevToolsWindow::InterceptPageBeforeUnload(contents)) {
    return true;
  }
  // If the WebContents is not connected yet, then there's no unload
  // handler we can fire even if the WebContents has an unload listener.
  // One case where we hit this is in a tab that has an infinite loop
  // before load.
  if (contents->NeedToFireBeforeUnloadOrUnloadEvents()) {
    // Inform PerformanceManager that the page is closing, so the priority of
    // its frames is boosted while beforeunload/unload handlers are running,
    // making page closing faster. This state may be reset in
    // BeforeUnloadFired() if page closing is aborted.
    performance_manager::execution_context_priority::SetPageIsClosing(
        contents, /*is_closing=*/true);

    // If the page has unload listeners, then we tell the renderer to fire
    // them. Once they have fired, we'll get a message back saying whether
    // to proceed closing the page or not, which sends us back to this method
    // with the NeedToFireBeforeUnloadOrUnloadEvents bit cleared.
    contents->DispatchBeforeUnload(false /* auto_cancel */);
    return true;
  }
  return false;
}

bool UnloadController::BeforeUnloadFired(content::WebContents* contents,
                                         bool proceed) {
  if (!proceed) {
    DevToolsWindow::OnPageCloseCanceled(contents);

    // Inform PerformanceManager that page close was aborted. Any priority boost
    // will be removed.
    performance_manager::execution_context_priority::SetPageIsClosing(
        contents, /*is_closing=*/false);

    std::optional<tab_groups::TabGroupId> group =
        browser_->tab_strip_model()->GetTabGroupForTab(
            browser_->tab_strip_model()->GetIndexOfWebContents(contents));
    if (group.has_value()) {
      TabGroup* const tab_group =
          browser_->tab_strip_model()->group_model()->GetTabGroup(
              group.value());
      if (tab_group->IsGroupClosing()) {
        browser_->tab_strip_model()->GroupCloseStopped(group.value());
      }
    }
  }

  if (!is_attempting_to_close_browser_) {
    if (!proceed) {
      contents->SetClosedByUserGesture(false);
    }
    return proceed;
  }

  if (!proceed) {
    CancelWindowClose();
    contents->SetClosedByUserGesture(false);
    return false;
  }

  if (RemoveFromSet(&tabs_needing_before_unload_fired_, contents)) {
    // Now that beforeunload has fired, put the tab on the queue to fire
    // unload.
    tabs_needing_unload_fired_.insert(contents);
    ProcessPendingTabs(false);
    // We want to handle firing the unload event ourselves since we want to
    // fire all the beforeunload events before attempting to fire the unload
    // events should the user cancel closing the browser.
    return false;
  }

  return true;
}

BrowserWindowInterface::ClosingStatus
UnloadController::GetBrowserClosingStatus() {
  if (IsUnclosableApp()) {
    return BrowserWindowInterface::ClosingStatus::kDeniedByPolicy;
  }

  if (HasCompletedUnloadProcessing()) {
    return BrowserWindowInterface::ClosingStatus::kPermitted;
  }

  // Special case for when we quit an application. The devtools window can
  // close if it's beforeunload event has already fired which will happen due
  // to the interception of it's content's beforeunload.
  if (browser_->is_type_devtools() &&
      DevToolsWindow::HasFiredBeforeUnloadEventForDevToolsBrowser(browser_)) {
    return BrowserWindowInterface::ClosingStatus::kPermitted;
  }

  // The behavior followed here varies based on the current phase of the
  // operation and whether a batched shutdown is in progress.
  //
  // If there are tabs with outstanding beforeunload handlers:
  // 1. If a batched shutdown is in progress: return false.
  //    This is to prevent interference with batched shutdown already in
  //    progress.
  // 2. Otherwise: start sending beforeunload events and return false.
  //
  // Otherwise, If there are no tabs with outstanding beforeunload handlers:
  // 3. If a batched shutdown is in progress: start sending unload events and
  //    return false.
  // 4. Otherwise: return true.
  is_attempting_to_close_browser_ = true;
  // Cases 1 and 4.
  tabs_needing_before_unload_fired_ = GetTabsNeedingBeforeUnloadFired();

  bool need_beforeunload_fired = !tabs_needing_before_unload_fired_.empty();
  if (need_beforeunload_fired == is_calling_before_unload_handlers()) {
    return need_beforeunload_fired
               ? BrowserWindowInterface::ClosingStatus::
                     kDeniedUnloadHandlersNeedTime
               : BrowserWindowInterface::ClosingStatus::kPermitted;
  }

  // Cases 2 and 3.
  on_close_confirmed_.Reset();
  ProcessPendingTabs(false);
  return BrowserWindowInterface::ClosingStatus::kDeniedUnloadHandlersNeedTime;
}

bool UnloadController::TryToCloseWindow(
    bool skip_beforeunload,
    const base::RepeatingCallback<void(bool)>& on_close_confirmed) {
  // The devtools browser gets its beforeunload events as the results of
  // intercepting events from the inspected tab, so don't send them here as
  // well.
  if (browser_->is_type_devtools() || HasCompletedUnloadProcessing()) {
    return false;
  }

  tabs_needing_before_unload_fired_ = GetTabsNeedingBeforeUnloadFired();
  if (tabs_needing_before_unload_fired_.empty()) {
    return false;
  }

  is_attempting_to_close_browser_ = true;
  on_close_confirmed_ = on_close_confirmed;

  ProcessPendingTabs(skip_beforeunload);
  return !skip_beforeunload;
}

void UnloadController::ResetTryToCloseWindow() {
  if (!is_calling_before_unload_handlers()) {
    return;
  }
  CancelWindowClose();
}

bool UnloadController::TabsNeedBeforeUnloadFired() const {
  return !GetTabsNeedingBeforeUnloadFired().empty();
}

UnloadController::UnloadListenerSet
UnloadController::GetTabsNeedingBeforeUnloadFired() const {
  if (!is_attempting_to_close_browser_) {
    CHECK(tabs_needing_unload_fired_.empty());
  }

  UnloadListenerSet tabs_needing_beforeunload;
  for (int i = 0; i < browser_->tab_strip_model()->count(); ++i) {
    content::WebContents* const contents =
        browser_->tab_strip_model()->GetWebContentsAt(i);
    const bool should_fire_beforeunload =
        contents->NeedToFireBeforeUnloadOrUnloadEvents() ||
        DevToolsWindow::NeedsToInterceptBeforeUnload(contents);
    // Note that we filter out tabs in `tabs_needing_unload_fired_` as they have
    // already had their BeforeUnload fired (and don't need it fired again
    // unless browser closing gets cancelled).
    if (!tabs_needing_unload_fired_.contains(contents) &&
        should_fire_beforeunload) {
      tabs_needing_beforeunload.insert(contents);
    }
  }
  return tabs_needing_beforeunload;
}

void UnloadController::CancelWindowClose() {
  // Note that this method may be called if closing was canceled in a number of
  // different ways, so is_attempting_to_close_browser_ may be false. In that
  // case some of this code might not have an effect, but it's still useful to,
  // for example, call the notification(s).
  tabs_needing_before_unload_fired_.clear();
  for (const auto& it : tabs_needing_unload_fired_) {
    DevToolsWindow::OnPageCloseCanceled(it);
  }
  tabs_needing_unload_fired_.clear();
  if (is_calling_before_unload_handlers()) {
    std::move(on_close_confirmed_).Run(false);
  }
  is_attempting_to_close_browser_ = false;

  chrome::OnClosingAllBrowsers(false);
}

////////////////////////////////////////////////////////////////////////////////
// UnloadController, WebContentsCollection::Observer implementation:

void UnloadController::RenderProcessGone(content::WebContents* web_contents,
                                         base::TerminationStatus status) {
  if (is_attempting_to_close_browser_) {
    ClearUnloadState(web_contents,
                     false);  // See comment for ClearUnloadState().
  }
  web_contents_collection_.StopObserving(web_contents);
}

////////////////////////////////////////////////////////////////////////////////
// UnloadController, TabStripModelObserver implementation:

void UnloadController::OnTabStripModelChanged(
    TabStripModel* tab_strip_model,
    const TabStripModelChange& change,
    const TabStripSelectionChange& selection) {
  std::vector<content::WebContents*> new_contents;
  std::vector<content::WebContents*> old_contents;

  if (change.type() == TabStripModelChange::kInserted) {
    for (const auto& contents : change.GetInsert()->contents) {
      new_contents.push_back(contents.contents);
    }
  } else if (change.type() == TabStripModelChange::kReplaced) {
    new_contents.push_back(change.GetReplace()->new_contents);
    old_contents.push_back(change.GetReplace()->old_contents);
  } else if (change.type() == TabStripModelChange::kRemoved) {
    for (const auto& contents : change.GetRemove()->contents) {
      old_contents.push_back(contents.contents);
    }
  }

  for (auto* contents : old_contents) {
    TabDetachedImpl(contents);
  }
  for (auto* contents : new_contents) {
    TabAttachedImpl(contents);
  }
}

void UnloadController::TabStripEmpty() {
  // Set is_attempting_to_close_browser_ here, so that extensions, etc, do not
  // attempt to add tabs to the browser before it closes.
  is_attempting_to_close_browser_ = true;
}

////////////////////////////////////////////////////////////////////////////////
// UnloadController, private:

void UnloadController::TabAttachedImpl(content::WebContents* contents) {
  // If the tab crashes in the beforeunload or unload handler, it won't be
  // able to ack. But we know we can close it.
  web_contents_collection_.StartObserving(contents);
}

void UnloadController::TabDetachedImpl(content::WebContents* contents) {
  if (is_attempting_to_close_browser_) {
    ClearUnloadState(contents, false);
  }
  // TODO(crbug.com/40054609): This CHECK is only in place to diagnose a UAF
  // bug. This is both used to confirm that a WebContents* isn't being removed
  // from this set, and also if that hypothesis is correct turns a UAF into a
  // non-security crash.
  CHECK(tabs_needing_before_unload_fired_.find(contents) ==
        tabs_needing_before_unload_fired_.end());
  web_contents_collection_.StopObserving(contents);
}

void UnloadController::ProcessPendingTabs(bool skip_beforeunload) {
  // Cancel posted/queued ProcessPendingTabs task if there is any.
  weak_factory_.InvalidateWeakPtrs();

  if (!is_attempting_to_close_browser_) {
    // Because we might invoke this after a delay it's possible for the value of
    // is_attempting_to_close_browser_ to have changed since we scheduled the
    // task.
    return;
  }

  if (HasCompletedUnloadProcessing()) {
    tabs_needing_before_unload_fired_ = GetTabsNeedingBeforeUnloadFired();
    if (tabs_needing_before_unload_fired_.empty()) {
      // We've finished all the unload events and can proceed to close the
      // browser.
      browser_->OnWindowClosing();
      return;
    }
  }

  if (skip_beforeunload) {
    tabs_needing_unload_fired_.insert(tabs_needing_before_unload_fired_.begin(),
                                      tabs_needing_before_unload_fired_.end());
    tabs_needing_before_unload_fired_.clear();
  }

  // Process beforeunload tabs first. When that queue is empty, process
  // unload tabs.
  if (!tabs_needing_before_unload_fired_.empty()) {
    content::WebContents* const web_contents =
        *(tabs_needing_before_unload_fired_.begin());
    // Null check render_view_host here as this gets called on a PostTask and
    // the tab's render_view_host may have been nulled out.
    if (web_contents->GetPrimaryMainFrame()->GetRenderViewHost()) {
      // If there's a devtools window attached to |web_contents|,
      // we would like devtools to call its own beforeunload handlers first,
      // and then call beforeunload handlers for |web_contents|.
      // See DevToolsWindow::InterceptPageBeforeUnload for details.
      if (!DevToolsWindow::InterceptPageBeforeUnload(web_contents)) {
        // Inform PerformanceManager that the page is closing, so the priority
        // of its frames is boosted while beforeunload/unload handlers are
        // running, making page closing faster. This state may be reset in
        // BeforeUnloadFired() if page closing is aborted.
        performance_manager::execution_context_priority::SetPageIsClosing(
            web_contents, /*is_closing=*/true);

        web_contents->DispatchBeforeUnload(false /* auto_cancel */);
      }
    } else {
      ClearUnloadState(web_contents, true);
    }
    return;
  }
  if (is_calling_before_unload_handlers()) {
    base::RepeatingCallback<void(bool)> on_close_confirmed =
        on_close_confirmed_;
    // Reset |on_close_confirmed_| in case the callback tests
    // |is_calling_before_unload_handlers()|, we want to return that calling
    // is complete.
    if (tabs_needing_unload_fired_.empty()) {
      on_close_confirmed_.Reset();
    }
    if (!skip_beforeunload) {
      on_close_confirmed.Run(true);
    }
    return;
  }
  CHECK(!tabs_needing_unload_fired_.empty());
  // We've finished firing all beforeunload events and can proceed with unload
  // events.
  // TODO(ojan): We should add a call to browser_shutdown::OnShutdownStarting
  // somewhere around here so that we have accurate measurements of shutdown
  // time.
  // TODO(ojan): We can probably fire all the unload events in parallel and
  // get a perf benefit from that in the cases where the tab hangs in it's
  // unload handler or takes a long time to page in.
  content::WebContents* const web_contents =
      *(tabs_needing_unload_fired_.begin());
  // Null check render_view_host here as this gets called on a PostTask and
  // the tab's render_view_host may have been nulled out.
  if (web_contents->GetPrimaryMainFrame()->GetRenderViewHost()) {
    web_contents->ClosePage();
  } else {
    ClearUnloadState(web_contents, true);
  }
}

bool UnloadController::HasCompletedUnloadProcessing() const {
  return is_attempting_to_close_browser_ &&
         tabs_needing_before_unload_fired_.empty() &&
         tabs_needing_unload_fired_.empty();
}

bool UnloadController::RemoveFromSet(UnloadListenerSet* set,
                                     content::WebContents* web_contents) {
  DCHECK(is_attempting_to_close_browser_);

  auto iter = std::ranges::find(*set, web_contents);
  if (iter != set->end()) {
    set->erase(iter);
    return true;
  }
  return false;
}

void UnloadController::ClearUnloadState(content::WebContents* web_contents,
                                        bool process_now) {
  if (is_attempting_to_close_browser_) {
    RemoveFromSet(&tabs_needing_before_unload_fired_, web_contents);
    RemoveFromSet(&tabs_needing_unload_fired_, web_contents);
    if (process_now) {
      ProcessPendingTabs(false);
    } else {
      // Do not post a new task if there is already any.
      if (weak_factory_.HasWeakPtrs()) {
        return;
      }
      base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
          FROM_HERE, base::BindOnce(&UnloadController::ProcessPendingTabs,
                                    weak_factory_.GetWeakPtr(), false));
    }
  }
}

bool UnloadController::IsUnclosableApp() const {
  if (!web_app::AppBrowserController::IsWebApp(browser_.get())) {
    return false;
  }

  content::WebContents* const active_web_contents =
      browser_->tab_strip_model()->GetActiveWebContents();
  if (!active_web_contents) {
    return false;
  }
  return web_app::WebAppProvider::GetForWebContents(active_web_contents)
      ->policy_manager()
      .IsPreventCloseEnabled(browser_->app_controller()->app_id());
}
