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

风清扬_jd 2024-10-15 10:03:02 阅读 55

一、前端代码

<code><!DOCTYPE html>

<html lang="en">code>

<head>

<meta charset="UTF-8">code>

<title>Test Alert</title>

<script>

function Test() {

alert("test");

}

</script>

</head>

<body>

<button onclick="Test()">Test Alert</button>code>

</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) 行 495C++已加载符号。

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

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) 行 102C++已加载符号。

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

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

 通过  // 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

<code>// 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形式。



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。