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