Chromium 中前端alert方法 c++代码实现

一、前端代码

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Test Alert</title>
<script>
function Test() {
 alert("test");
}
</script>
</head>
<body>
 
<button onclick="Test()">Test Alert</button>
 
</body>
</html>

二、c++代码实现alert分析

1、在third_party\blink\public\mojom\frame\frame.mojom 定义接口

    

  // A request to run a JavaScript dialog displaying |alert_message|.
  [Sync]
  RunModalAlertDialog(mojo_base.mojom.String16 alert_message,
                      bool disable_third_party_subframe_suppresion) => ();

2、分别在主进程和binlk中实现mojom对应代码

   1)、主进程content\browser\renderer_host\render_frame_host_impl.cc

          

void RenderFrameHostImpl::RunModalAlertDialog(
    const std::u16string& alert_message,
    bool disable_third_party_subframe_suppresion,
    RunModalAlertDialogCallback response_callback) {
  auto dialog_closed_callback = base::BindOnce(
      [](RunModalAlertDialogCallback response_callback, bool success,
         const std::u16string& response) {
        // The response string is unused but we use a generic mechanism for
        // closing the javascript dialog that returns two arguments.
        std::move(response_callback).Run();
      },
      std::move(response_callback));
  RunJavaScriptDialog(alert_message, std::u16string(),
                      JAVASCRIPT_DIALOG_TYPE_ALERT,
                      disable_third_party_subframe_suppresion,
                      std::move(dialog_closed_callback));
}

  具体view创建代码在chrome\browser\ui\views\javascript_tab_modal_dialog_view_views.cc

 

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

#include "base/functional/callback.h"
#include "chrome/browser/ui/javascript_dialogs/javascript_tab_modal_dialog_manager_delegate_desktop.h"
#include "chrome/browser/ui/views/title_origin_label.h"
#include "components/constrained_window/constrained_window_views.h"
#include "content/public/browser/javascript_dialog_manager.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/strings/grit/ui_strings.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/bubble/bubble_frame_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/message_box_view.h"
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/layout/fill_layout.h"

JavaScriptTabModalDialogViewViews::~JavaScriptTabModalDialogViewViews() =
    default;

void JavaScriptTabModalDialogViewViews::CloseDialogWithoutCallback() {
  dialog_callback_.Reset();
  dialog_force_closed_callback_.Reset();
  GetWidget()->Close();
}

std::u16string JavaScriptTabModalDialogViewViews::GetUserInput() {
  return message_box_view_->GetInputText();
}

std::u16string JavaScriptTabModalDialogViewViews::GetWindowTitle() const {
  return title_;
}

bool JavaScriptTabModalDialogViewViews::ShouldShowCloseButton() const {
  return false;
}

views::View* JavaScriptTabModalDialogViewViews::GetInitiallyFocusedView() {
  auto* text_box = message_box_view_->GetVisiblePromptField();
  return text_box ? text_box : views::DialogDelegate::GetInitiallyFocusedView();
}

void JavaScriptTabModalDialogViewViews::AddedToWidget() {
  auto* bubble_frame_view = static_cast<views::BubbleFrameView*>(
      GetWidget()->non_client_view()->frame_view());
  bubble_frame_view->SetTitleView(CreateTitleOriginLabel(GetWindowTitle()));
  if (!message_text_.empty()) {
    GetWidget()->GetRootView()->GetViewAccessibility().OverrideDescription(
        message_text_);
  }
  // On some platforms, the platform accessibility API automatically
  // calculates the name of the native window based on the child RootView.
  // We override that calculation here so that we can present both the
  // title (e.g. "url.com says") and the message text on platforms where
  // the accessible description is ignored.
  GetViewAccessibility().OverrideNativeWindowTitle(l10n_util::GetStringFUTF16(
      IDS_CONCAT_TWO_STRINGS_WITH_COMMA, GetWindowTitle(), message_text_));
}

JavaScriptTabModalDialogViewViews::JavaScriptTabModalDialogViewViews(
    content::WebContents* parent_web_contents,
    content::WebContents* alerting_web_contents,
    const std::u16string& title,
    content::JavaScriptDialogType dialog_type,
    const std::u16string& message_text,
    const std::u16string& default_prompt_text,
    content::JavaScriptDialogManager::DialogClosedCallback dialog_callback,
    base::OnceClosure dialog_force_closed_callback)
    : title_(title),
      message_text_(message_text),
      default_prompt_text_(default_prompt_text),
      dialog_callback_(std::move(dialog_callback)),
      dialog_force_closed_callback_(std::move(dialog_force_closed_callback)) {
  SetModalType(ui::MODAL_TYPE_CHILD);
  SetDefaultButton(ui::DIALOG_BUTTON_OK);
  const bool is_alert = dialog_type == content::JAVASCRIPT_DIALOG_TYPE_ALERT;
  SetButtons(
      // Alerts only have an OK button, no Cancel, because there is no choice
      // being made.
      is_alert ? ui::DIALOG_BUTTON_OK
               : (ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL));

  SetAcceptCallback(base::BindOnce(
      [](JavaScriptTabModalDialogViewViews* dialog) {
        // Remove the force-close callback to indicate that we were closed as a
        // result of user action.
        dialog->dialog_force_closed_callback_ = base::OnceClosure();
        if (dialog->dialog_callback_)
          std::move(dialog->dialog_callback_)
              .Run(true, dialog->message_box_view_->GetInputText());
      },
      base::Unretained(this)));
  SetCancelCallback(base::BindOnce(
      [](JavaScriptTabModalDialogViewViews* dialog) {
        // Remove the force-close callback to indicate that we were closed as a
        // result of user action.
        dialog->dialog_force_closed_callback_ = base::OnceClosure();
        if (dialog->dialog_callback_)
          std::move(dialog->dialog_callback_).Run(false, std::u16string());
      },
      base::Unretained(this)));
  RegisterWindowWillCloseCallback(base::BindOnce(
      [](JavaScriptTabModalDialogViewViews* dialog) {
        // If the force-close callback still exists at this point we're not
        // closed due to a user action (would've been caught in Accept/Cancel).
        if (dialog->dialog_force_closed_callback_)
          std::move(dialog->dialog_force_closed_callback_).Run();
      },
      base::Unretained(this)));

  message_box_view_ = new views::MessageBoxView(
      message_text, /* detect_directionality = */ true);
  if (dialog_type == content::JAVASCRIPT_DIALOG_TYPE_PROMPT)
    message_box_view_->SetPromptField(default_prompt_text);

  SetLayoutManager(std::make_unique<views::FillLayout>());
  AddChildView(message_box_view_.get());

  constrained_window::ShowWebModalDialogViews(this, parent_web_contents);
}

// static
JavaScriptTabModalDialogViewViews*
JavaScriptTabModalDialogViewViews::CreateAlertDialogForTesting(
    Browser* browser,
    std::u16string title,
    std::u16string message) {
  return new JavaScriptTabModalDialogViewViews(
      browser->tab_strip_model()->GetActiveWebContents(),
      browser->tab_strip_model()->GetActiveWebContents(), title,
      content::JAVASCRIPT_DIALOG_TYPE_ALERT, message, std::u16string(),
      base::NullCallback(), base::NullCallback());
}

BEGIN_METADATA(JavaScriptTabModalDialogViewViews, views::DialogDelegateView)
END_METADATA

// Creates a new JS dialog. Note the two callbacks; |dialog_callback| is for
// user responses, while |dialog_force_closed_callback| is for when Views
// forces the dialog closed without a user reply.
base::WeakPtr<javascript_dialogs::TabModalDialogView>
JavaScriptTabModalDialogManagerDelegateDesktop::CreateNewDialog(
    content::WebContents* alerting_web_contents,
    const std::u16string& title,
    content::JavaScriptDialogType dialog_type,
    const std::u16string& message_text,
    const std::u16string& default_prompt_text,
    content::JavaScriptDialogManager::DialogClosedCallback dialog_callback,
    base::OnceClosure dialog_force_closed_callback) {
  return (new JavaScriptTabModalDialogViewViews(
              web_contents_, alerting_web_contents, title, dialog_type,
              message_text, default_prompt_text, std::move(dialog_callback),
              std::move(dialog_force_closed_callback)))
      ->weak_factory_.GetWeakPtr();
}

2)、blink中实现代码

  third_party\blink\renderer\core\page\chrome_client_impl.cc



bool ChromeClientImpl::OpenJavaScriptAlertDelegate(LocalFrame* frame,
                                                   const String& message) {
  NotifyPopupOpeningObservers();
  bool disable_suppression = false;
  if (frame && frame->GetDocument()) {
    disable_suppression = RuntimeEnabledFeatures::
        DisableDifferentOriginSubframeDialogSuppressionEnabled(
            frame->GetDocument()->GetExecutionContext());
  }
  // Synchronous mojo call.
  frame->GetLocalFrameHostRemote().RunModalAlertDialog(
      TruncateDialogMessage(message), disable_suppression);
  return true;
}

三、调用堆栈分析

1、前端执行alert之后c++调用AlertOperationCallback 此刻在新标签的进程非主进程。

【进程ID7180 打开的新标签】

【进程ID12896 主进程】

out\Debug\gen\third_party\blink\renderer\bindings\modules\v8\v8_window.cc

void AlertOperationCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
  RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(info.GetIsolate(), "Blink_DOMWindow_alert");
BLINK_BINDINGS_TRACE_EVENT("Window.alert");

scheduler::CooperativeSchedulingManager::Instance()->Safepoint();

const int arg_count = std::min(info.Length(), 1);
if (arg_count == 1) {
  return AlertOperationOverload2(info);
}
return AlertOperationOverload1(info);
}

2、调用堆栈

blink_core.dll!blink::ChromeClientImpl::OpenJavaScriptAlertDelegate(blink::LocalFrame * frame, const WTF::String & message) 行 495	C++	已加载符号。

 	blink_core.dll!blink::ChromeClient::OpenJavaScriptAlert::<lambda_1>::operator()() 行 124	C++	已加载符号。

 	blink_core.dll!blink::OpenJavaScriptDialog<`lambda at ..\..\third_party\blink\renderer\core\page\chrome_client.cc:123:47'>(blink::LocalFrame * frame, const WTF::String & message, const blink::ChromeClient::OpenJavaScriptAlert::<lambda_1> & delegate) 行 102	C++	已加载符号。

 	blink_core.dll!blink::ChromeClient::OpenJavaScriptAlert(blink::LocalFrame * frame, const WTF::String & message) 行 123	C++	已加载符号。

 	blink_core.dll!blink::LocalDOMWindow::alert(blink::ScriptState * script_state, const WTF::String & message) 行 1370	C++	已加载符号。

 通过  // Synchronous mojo call.
  frame->GetLocalFrameHostRemote().RunModalAlertDialog(
      TruncateDialogMessage(message), disable_suppression);

发送给主进程【进程ID12896 主进程】RunModalAlertDialog函数处理!!!

void RenderFrameHostImpl::RunModalAlertDialog(
    const std::u16string& alert_message,
    bool disable_third_party_subframe_suppresion,
    RunModalAlertDialogCallback response_callback) {
  auto dialog_closed_callback = base::BindOnce(
      [](RunModalAlertDialogCallback response_callback, bool success,
         const std::u16string& response) {
        // The response string is unused but we use a generic mechanism for
        // closing the javascript dialog that returns two arguments.
        std::move(response_callback).Run();
      },
      std::move(response_callback));
  RunJavaScriptDialog(alert_message, std::u16string(),
                      JAVASCRIPT_DIALOG_TYPE_ALERT,
                      disable_third_party_subframe_suppresion,
                      std::move(dialog_closed_callback));
}

响应此处理

【以下是主进程堆栈】

chrome\browser\ui\views\javascript_tab_modal_dialog_view_views.cc

// Creates a new JS dialog. Note the two callbacks; |dialog_callback| is for
// user responses, while |dialog_force_closed_callback| is for when Views
// forces the dialog closed without a user reply.
base::WeakPtr<javascript_dialogs::TabModalDialogView>
JavaScriptTabModalDialogManagerDelegateDesktop::CreateNewDialog(
    content::WebContents* alerting_web_contents,
    const std::u16string& title,
    content::JavaScriptDialogType dialog_type,
    const std::u16string& message_text,
    const std::u16string& default_prompt_text,
    content::JavaScriptDialogManager::DialogClosedCallback dialog_callback,
    base::OnceClosure dialog_force_closed_callback) {
  return (new JavaScriptTabModalDialogViewViews(
              web_contents_, alerting_web_contents, title, dialog_type,
              message_text, default_prompt_text, std::move(dialog_callback),
              std::move(dialog_force_closed_callback)))
      ->weak_factory_.GetWeakPtr();
}

可以看到 alert_message=“test”即使前端写入的值。本例动态修改值为alert_message="tes8"

看下效果:

 

至此分析完毕。

如果想要改前端alert内容可以在此拦截等,chrome定义的前端接口多数是以.idl .mojom,.json形式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值