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

#include "components/javascript_dialogs/tab_modal_dialog_manager.h"

#include <utility>

#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/stringprintf.h"
#include "components/javascript_dialogs/app_modal_dialog_manager.h"
#include "components/javascript_dialogs/tab_modal_dialog_view.h"
#include "components/navigation_metrics/navigation_metrics.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "ui/gfx/text_elider.h"
#include "url/origin.h"

namespace javascript_dialogs {

namespace {

AppModalDialogManager* GetAppModalDialogManager() {
  return AppModalDialogManager::GetInstance();
}

}  // namespace

TabModalDialogManager::~TabModalDialogManager() {
  CloseDialog(DismissalCause::kTabHelperDestroyed, false, std::u16string());
}

void TabModalDialogManager::BrowserActiveStateChanged() {
  if (delegate_->IsWebContentsForemost())
    OnVisibilityChanged(content::Visibility::VISIBLE);
  else
    HandleTabSwitchAway(DismissalCause::kBrowserSwitched);
}

void TabModalDialogManager::CloseDialogWithReason(DismissalCause reason) {
  CloseDialog(reason, false, std::u16string());
}

void TabModalDialogManager::SetDialogShownCallbackForTesting(
    base::OnceClosure callback) {
  dialog_shown_ = std::move(callback);
}

bool TabModalDialogManager::IsShowingDialogForTesting() const {
  return !!dialog_;
}

void TabModalDialogManager::ClickDialogButtonForTesting(
    bool accept,
    const std::u16string& user_input) {
  DCHECK(!!dialog_);
  CloseDialog(DismissalCause::kDialogButtonClicked, accept, user_input);
}

void TabModalDialogManager::SetDialogDismissedCallbackForTesting(
    DialogDismissedCallback callback) {
  dialog_dismissed_ = std::move(callback);
}

void TabModalDialogManager::RunJavaScriptDialog(
    content::WebContents* alerting_web_contents,
    content::RenderFrameHost* render_frame_host,
    content::JavaScriptDialogType dialog_type,
    const std::u16string& message_text,
    const std::u16string& default_prompt_text,
    DialogClosedCallback callback,
    bool* did_suppress_message) {
  DCHECK_EQ(alerting_web_contents,
            content::WebContents::FromRenderFrameHost(render_frame_host));

  content::WebContents* web_contents = WebContentsObserver::web_contents();

  // Close any dialog already showing.
  CloseDialog(DismissalCause::kSubsequentDialogShown, false, std::u16string());

  // Only show the dialog if there is no other modal dialog showing.
  if (!delegate_->CanShowModalUI()) {
    static const char kDialogSuppressedByOtherDialogConsoleMessageFormat[] =
        "A window.%s() dialog generated by this page was suppressed because "
        "another browser modal dialog was already showing to the user.";
    std::string dialog_type_string;
    switch (dialog_type) {
      case content::JAVASCRIPT_DIALOG_TYPE_ALERT: {
        dialog_type_string = "alert";
        break;
      }
      case content::JAVASCRIPT_DIALOG_TYPE_CONFIRM: {
        dialog_type_string = "confirm";
        break;
      }
      case content::JAVASCRIPT_DIALOG_TYPE_PROMPT: {
        dialog_type_string = "prompt";
        break;
      }
    }
    render_frame_host->AddMessageToConsole(
        blink::mojom::ConsoleMessageLevel::kWarning,
        base::StringPrintf(kDialogSuppressedByOtherDialogConsoleMessageFormat,
                           dialog_type_string.c_str()));

    *did_suppress_message = true;
    return;
  }

  bool make_pending = false;
  if (!delegate_->IsWebContentsForemost() &&
      !content::DevToolsAgentHost::IsDebuggerAttached(web_contents)) {
    static const char kDialogSuppressedConsoleMessageFormat[] =
        "A window.%s() dialog generated by this page was suppressed "
        "because this page is not the active tab of the front window. "
        "Please make sure your dialogs are triggered by user interactions "
        "to avoid this situation. https://www.chromestatus.com/feature/%s";

    switch (dialog_type) {
      case content::JAVASCRIPT_DIALOG_TYPE_ALERT: {
        // When an alert fires in the background, make the callback so that the
        // render process can continue.
        std::move(callback).Run(true, std::u16string());
        callback.Reset();

        delegate_->SetTabNeedsAttention(true);

        make_pending = true;
        break;
      }
      case content::JAVASCRIPT_DIALOG_TYPE_CONFIRM: {
        *did_suppress_message = true;
        render_frame_host->AddMessageToConsole(
            blink::mojom::ConsoleMessageLevel::kWarning,
            base::StringPrintf(kDialogSuppressedConsoleMessageFormat, "confirm",
                               "5140698722467840"));
        return;
      }
      case content::JAVASCRIPT_DIALOG_TYPE_PROMPT: {
        *did_suppress_message = true;
        render_frame_host->AddMessageToConsole(
            blink::mojom::ConsoleMessageLevel::kWarning,
            base::StringPrintf(kDialogSuppressedConsoleMessageFormat, "prompt",
                               "5637107137642496"));
        return;
      }
    }
  }

  // Enforce sane sizes. ElideRectangleString breaks horizontally, which isn't
  // strictly needed, but it restricts the vertical size, which is crucial.
  // This gives about 2000 characters, which is about the same as the
  // AppModalDialogManager provides, but allows no more than 24 lines.
  const int kMessageTextMaxRows = 24;
  const int kMessageTextMaxCols = 80;
  const size_t kDefaultPromptMaxSize = 2000;
  std::u16string truncated_message_text;
  gfx::ElideRectangleString(message_text, kMessageTextMaxRows,
                            kMessageTextMaxCols, false,
                            &truncated_message_text);
  std::u16string truncated_default_prompt_text;
  gfx::ElideString(default_prompt_text, kDefaultPromptMaxSize,
                   &truncated_default_prompt_text);

  std::u16string title = GetAppModalDialogManager()->GetTitle(
      alerting_web_contents, render_frame_host->GetLastCommittedOrigin());
  dialog_callback_ = std::move(callback);
  dialog_type_ = dialog_type;
  if (make_pending) {
    DCHECK(!dialog_);
    pending_dialog_ = base::BindOnce(
        &TabModalDialogManagerDelegate::CreateNewDialog,
        base::Unretained(delegate_.get()), alerting_web_contents, title,
        dialog_type, truncated_message_text, truncated_default_prompt_text,
        base::BindOnce(&TabModalDialogManager::CloseDialog,
                       base::Unretained(this),
                       DismissalCause::kDialogButtonClicked),
        base::BindOnce(&TabModalDialogManager::CloseDialog,
                       base::Unretained(this), DismissalCause::kDialogClosed,
                       false, std::u16string()));
  } else {
    DCHECK(!pending_dialog_);
    dialog_ = delegate_->CreateNewDialog(
        alerting_web_contents, title, dialog_type, truncated_message_text,
        truncated_default_prompt_text,
        base::BindOnce(&TabModalDialogManager::CloseDialog,
                       base::Unretained(this),
                       DismissalCause::kDialogButtonClicked),
        base::BindOnce(&TabModalDialogManager::CloseDialog,
                       base::Unretained(this), DismissalCause::kDialogClosed,
                       false, std::u16string()));
  }

  delegate_->WillRunDialog();

  // Message suppression is something that we don't give the user a checkbox
  // for any more. It was useful back in the day when dialogs were app-modal
  // and clicking the checkbox was the only way to escape a loop that the page
  // was doing, but now the user can just close the page.
  *did_suppress_message = false;

  if (!dialog_shown_.is_null())
    std::move(dialog_shown_).Run();
}

void TabModalDialogManager::RunBeforeUnloadDialog(
    content::WebContents* web_contents,
    content::RenderFrameHost* render_frame_host,
    bool is_reload,
    DialogClosedCallback callback) {
  DCHECK_EQ(web_contents,
            content::WebContents::FromRenderFrameHost(render_frame_host));

  // onbeforeunload dialogs are always handled with an app-modal dialog, because
  // - they are critical to the user not losing data
  // - they can be requested for tabs that are not foremost
  // - they can be requested for many tabs at the same time
  // and therefore auto-dismissal is inappropriate for them.

  return GetAppModalDialogManager()->RunBeforeUnloadDialogWithOptions(
      web_contents, render_frame_host, is_reload, delegate_->IsApp(),
      std::move(callback));
}

bool TabModalDialogManager::HandleJavaScriptDialog(
    content::WebContents* web_contents,
    bool accept,
    const std::u16string* prompt_override) {
  if (dialog_ || pending_dialog_) {
    CloseDialog(DismissalCause::kHandleDialogCalled, accept,
                prompt_override ? *prompt_override : dialog_->GetUserInput());
    return true;
  }

  // Handle any app-modal dialogs being run by the app-modal dialog system.
  return GetAppModalDialogManager()->HandleJavaScriptDialog(
      web_contents, accept, prompt_override);
}

void TabModalDialogManager::CancelDialogs(content::WebContents* web_contents,
                                          bool reset_state) {
  CloseDialog(DismissalCause::kCancelDialogsCalled, false, std::u16string());

  // Cancel any app-modal dialogs being run by the app-modal dialog system.
  return GetAppModalDialogManager()->CancelDialogs(web_contents, reset_state);
}

void TabModalDialogManager::OnVisibilityChanged(
    content::Visibility visibility) {
  if (visibility == content::Visibility::HIDDEN) {
    HandleTabSwitchAway(DismissalCause::kTabHidden);
  } else if (pending_dialog_) {
    // Another dialog has started showing between when the pending dialog was
    // created and now. We cannot show the pending dialog over the currently
    // showing dialog, so we must close the pending dialog.
    if (!delegate_->CanShowModalUI()) {
      CloseDialog(DismissalCause::kSuppressedByOtherDialog, false,
                  std::u16string());
      return;
    }

    dialog_ = std::move(pending_dialog_).Run();
    pending_dialog_.Reset();
    delegate_->SetTabNeedsAttention(false);
  }
}

void TabModalDialogManager::DidStartNavigation(
    content::NavigationHandle* navigation_handle) {
  if (!navigation_handle->IsInPrimaryMainFrame())
    return;

  // Close the dialog if the user started a new navigation. This allows reloads
  // and history navigations to proceed.
  CloseDialog(DismissalCause::kTabNavigated, false, std::u16string());
}

TabModalDialogManager::TabModalDialogManager(
    content::WebContents* web_contents,
    std::unique_ptr<TabModalDialogManagerDelegate> delegate)
    : content::WebContentsObserver(web_contents),
      content::WebContentsUserData<TabModalDialogManager>(*web_contents),
      delegate_(std::move(delegate)) {}

void TabModalDialogManager::LogDialogDismissalCause(DismissalCause cause) {
  if (dialog_dismissed_)
    std::move(dialog_dismissed_).Run(cause);

  // Log to UKM.
  //
  // Note that this will return the outermost WebContents, not necessarily the
  // WebContents that had the alert call in it. For 99.9999% of cases they're
  // the same, but for instances like the <webview> tag in extensions and PDF
  // files that alert they may differ.
  ukm::SourceId source_id = WebContentsObserver::web_contents()
                                ->GetPrimaryMainFrame()
                                ->GetPageUkmSourceId();
  if (source_id != ukm::kInvalidSourceId) {
    ukm::builders::AbusiveExperienceHeuristic_JavaScriptDialog(source_id)
        .SetDismissalCause(static_cast<int64_t>(cause))
        .Record(ukm::UkmRecorder::Get());
  }
}

void TabModalDialogManager::HandleTabSwitchAway(DismissalCause cause) {
  if (!dialog_ || content::DevToolsAgentHost::IsDebuggerAttached(
                      WebContentsObserver::web_contents())) {
    return;
  }

  if (dialog_type_ == content::JAVASCRIPT_DIALOG_TYPE_ALERT) {
    // When the user switches tabs, make the callback so that the render process
    // can continue.
    if (dialog_callback_) {
      std::move(dialog_callback_).Run(true, std::u16string());
      dialog_callback_.Reset();
    }
  } else {
    CloseDialog(cause, false, std::u16string());
  }
}

void TabModalDialogManager::CloseDialog(DismissalCause cause,
                                        bool success,
                                        const std::u16string& user_input) {
  if (!dialog_ && !pending_dialog_)
    return;

  LogDialogDismissalCause(cause);

  // CloseDialog() can be called two ways. It can be called from within
  // TabModalDialogManager, in which case the dialog needs to be closed.
  // However, it can also be called, bound, from the JavaScriptDialog. In that
  // case, the dialog is already closing, so the JavaScriptDialog doesn't need
  // to be told to close.
  //
  // Using the |cause| to distinguish a call from JavaScriptDialog vs from
  // within TabModalDialogManager is a bit hacky, but is the simplest way.
  if (dialog_ && cause != DismissalCause::kDialogButtonClicked &&
      cause != DismissalCause::kDialogClosed)
    dialog_->CloseDialogWithoutCallback();

  // If there is a callback, call it. There might not be one, if a tab-modal
  // alert() dialog is showing.
  if (dialog_callback_)
    std::move(dialog_callback_).Run(success, user_input);

  // If there's a pending dialog, then the tab is still in the "needs attention"
  // state; clear it out. However, if the tab was switched out, the turning off
  // of the "needs attention" state was done in OnTabStripModelChanged()
  // SetTabNeedsAttention won't work, so don't call it.
  if (pending_dialog_ && cause != DismissalCause::kTabSwitchedOut &&
      cause != DismissalCause::kTabHelperDestroyed) {
    delegate_->SetTabNeedsAttention(false);
  }

  dialog_.reset();
  pending_dialog_.Reset();
  dialog_callback_.Reset();

  delegate_->DidCloseDialog();
}

WEB_CONTENTS_USER_DATA_KEY_IMPL(TabModalDialogManager);

}  // namespace javascript_dialogs
