Ladybird: Move ownership of the JS console/inspector to the tab object

This is to match Browser, where ownership of all "subwidgets" is placed
on the tab as well. This further lets us align the web view callbacks to
match Browser's OOPWV as well, which will later let us move them into
the base LibWebView class.
This commit is contained in:
Timothy Flynn 2023-05-17 11:54:36 -04:00 committed by Andreas Kling
parent 2d51b8c286
commit c113d780c6
Notes: sideshowbarker 2024-07-17 08:13:43 +09:00
9 changed files with 147 additions and 134 deletions

View file

@ -149,7 +149,7 @@ BrowserWindow::BrowserWindow(Browser::CookieJar& cookie_jar, StringView webdrive
inspect_menu->addAction(js_console_action);
QObject::connect(js_console_action, &QAction::triggered, this, [this] {
if (m_current_tab) {
m_current_tab->view().show_js_console();
m_current_tab->show_console_window();
}
});
@ -159,7 +159,7 @@ BrowserWindow::BrowserWindow(Browser::CookieJar& cookie_jar, StringView webdrive
inspect_menu->addAction(inspector_action);
QObject::connect(inspector_action, &QAction::triggered, this, [this] {
if (m_current_tab) {
m_current_tab->view().show_inspector();
m_current_tab->show_inspector_window();
}
});
@ -333,7 +333,7 @@ BrowserWindow::BrowserWindow(Browser::CookieJar& cookie_jar, StringView webdrive
m_inspect_dom_node_action = make<QAction>("&Inspect Element", this);
connect(m_inspect_dom_node_action, &QAction::triggered, this, [this] {
if (m_current_tab)
m_current_tab->view().show_inspector(WebContentView::InspectorTarget::HoveredElement);
m_current_tab->show_inspector_window(Tab::InspectorTarget::HoveredElement);
});
m_go_back_action = make<QAction>("Go Back");
connect(m_go_back_action, &QAction::triggered, this, [this] {
@ -580,7 +580,7 @@ void BrowserWindow::select_all()
if (!m_current_tab)
return;
if (auto* console = m_current_tab->view().console(); console && console->isActiveWindow())
if (auto* console = m_current_tab->console(); console && console->isActiveWindow())
console->view().select_all();
else
m_current_tab->view().select_all();
@ -601,7 +601,7 @@ void BrowserWindow::copy_selected_text()
DeprecatedString text;
if (auto* console = m_current_tab->view().console(); console && console->isActiveWindow())
if (auto* console = m_current_tab->console(); console && console->isActiveWindow())
text = console->view().selected_text();
else
text = m_current_tab->view().selected_text();

View file

@ -7,6 +7,8 @@
#include "Tab.h"
#include "BrowserWindow.h"
#include "ConsoleWidget.h"
#include "InspectorWidget.h"
#include "Settings.h"
#include "Utilities.h"
#include <Browser/History.h>
@ -142,7 +144,21 @@ Tab::Tab(BrowserWindow* window, StringView webdriver_content_ipc_path, WebView::
m_window->go_back_action().setEnabled(m_history.can_go_back());
m_window->go_forward_action().setEnabled(m_history.can_go_forward());
if (m_inspector_widget)
m_inspector_widget->clear_dom_json();
if (m_console_widget)
m_console_widget->reset();
});
view().on_load_finish = [this](auto&) {
if (m_inspector_widget != nullptr && m_inspector_widget->isVisible()) {
view().inspect_dom_tree();
view().inspect_accessibility_tree();
}
};
QObject::connect(m_location_edit, &QLineEdit::returnPressed, this, &Tab::location_edit_return_pressed);
QObject::connect(m_view, &WebContentView::title_changed, this, &Tab::page_title_changed);
QObject::connect(m_view, &WebContentView::favicon_changed, this, &Tab::page_favicon_changed);
@ -184,6 +200,26 @@ Tab::Tab(BrowserWindow* window, StringView webdriver_content_ipc_path, WebView::
return Gfx::IntRect { m_window->x(), m_window->y(), m_window->width(), m_window->height() };
});
view().on_get_dom_tree = [this](auto& dom_tree) {
if (m_inspector_widget)
m_inspector_widget->set_dom_json(dom_tree);
};
view().on_get_accessibility_tree = [this](auto& accessibility_tree) {
if (m_inspector_widget)
m_inspector_widget->set_accessibility_json(accessibility_tree);
};
view().on_js_console_new_message = [this](auto message_index) {
if (m_console_widget)
m_console_widget->notify_about_new_console_message(message_index);
};
view().on_get_js_console_messages = [this](auto start_index, auto& message_types, auto& messages) {
if (m_console_widget)
m_console_widget->handle_console_messages(start_index, message_types, messages);
};
auto* take_visible_screenshot_action = new QAction("Take &Visible Screenshot", this);
take_visible_screenshot_action->setIcon(QIcon(QString("%1/res/icons/16x16/filetype-image.png").arg(s_serenity_resource_root.characters())));
QObject::connect(take_visible_screenshot_action, &QAction::triggered, this, [this]() {
@ -378,6 +414,11 @@ Tab::Tab(BrowserWindow* window, StringView webdriver_content_ipc_path, WebView::
};
}
Tab::~Tab()
{
close_sub_widgets();
}
void Tab::update_reset_zoom_button()
{
auto zoom_level = view().zoom_level();
@ -506,3 +547,63 @@ void Tab::rerender_toolbar_icons()
m_window->go_forward_action().setIcon(render_svg_icon_with_theme_colors("forward", palette()));
m_window->reload_action().setIcon(render_svg_icon_with_theme_colors("reload", palette()));
}
void Tab::show_inspector_window(InspectorTarget inspector_target)
{
bool inspector_previously_loaded = m_inspector_widget != nullptr;
if (!m_inspector_widget) {
m_inspector_widget = new Ladybird::InspectorWidget;
m_inspector_widget->setWindowTitle("Inspector");
m_inspector_widget->resize(640, 480);
m_inspector_widget->on_close = [this] {
view().clear_inspected_dom_node();
};
m_inspector_widget->on_dom_node_inspected = [&](auto id, auto pseudo_element) {
return view().inspect_dom_node(id, pseudo_element);
};
}
if (!inspector_previously_loaded || !m_inspector_widget->dom_loaded()) {
view().inspect_dom_tree();
view().inspect_accessibility_tree();
}
m_inspector_widget->show();
if (inspector_target == InspectorTarget::HoveredElement) {
auto hovered_node = view().get_hovered_node_id();
m_inspector_widget->set_selection({ hovered_node });
} else {
m_inspector_widget->select_default_node();
}
}
void Tab::show_console_window()
{
if (!m_console_widget) {
m_console_widget = new Ladybird::ConsoleWidget;
m_console_widget->setWindowTitle("JS Console");
m_console_widget->resize(640, 480);
m_console_widget->on_js_input = [this](auto js_source) {
view().js_console_input(js_source);
};
m_console_widget->on_request_messages = [this](i32 start_index) {
view().js_console_request_messages(start_index);
};
}
m_console_widget->show();
}
void Tab::close_sub_widgets()
{
auto close_widget_window = [](auto* widget) {
if (widget)
widget->close();
};
close_widget_window(m_console_widget);
close_widget_window(m_inspector_widget);
}

View file

@ -19,10 +19,16 @@
class BrowserWindow;
namespace Ladybird {
class ConsoleWidget;
class InspectorWidget;
}
class Tab final : public QWidget {
Q_OBJECT
public:
Tab(BrowserWindow* window, StringView webdriver_content_ipc_path, WebView::EnableCallgrindProfiling);
virtual ~Tab() override;
WebContentView& view() { return *m_view; }
@ -36,6 +42,15 @@ public:
void update_reset_zoom_button();
enum class InspectorTarget {
Document,
HoveredElement
};
void show_inspector_window(InspectorTarget = InspectorTarget::Document);
void show_console_window();
Ladybird::ConsoleWidget* console() { return m_console_widget; };
public slots:
void focus_location_editor();
void location_edit_return_pressed();
@ -60,6 +75,8 @@ private:
void open_link_in_new_tab(URL const&);
void copy_link_url(URL const&);
void close_sub_widgets();
QBoxLayout* m_layout;
QToolBar* m_toolbar { nullptr };
QToolButton* m_reset_zoom_button { nullptr };
@ -91,4 +108,7 @@ private:
int tab_index();
bool m_is_history_navigation { false };
Ladybird::ConsoleWidget* m_console_widget { nullptr };
Ladybird::InspectorWidget* m_inspector_widget { nullptr };
};

View file

@ -6,9 +6,7 @@
*/
#include "WebContentView.h"
#include "ConsoleWidget.h"
#include "HelperProcess.h"
#include "InspectorWidget.h"
#include "Utilities.h"
#include <AK/Assertions.h>
#include <AK/ByteBuffer.h>
@ -32,7 +30,6 @@
#include <LibGfx/Palette.h>
#include <LibGfx/Rect.h>
#include <LibGfx/SystemTheme.h>
#include <LibJS/Runtime/ConsoleObject.h>
#include <LibMain/Main.h>
#include <LibWeb/Crypto/Crypto.h>
#include <LibWeb/Loader/ContentFilter.h>
@ -79,10 +76,7 @@ WebContentView::WebContentView(StringView webdriver_content_ipc_path, WebView::E
create_client(enable_callgrind_profiling);
}
WebContentView::~WebContentView()
{
close_sub_widgets();
}
WebContentView::~WebContentView() = default;
unsigned get_button_from_qt_event(QMouseEvent const& event)
{
@ -463,76 +457,6 @@ void WebContentView::update_viewport_rect()
request_repaint();
}
void WebContentView::ensure_js_console_widget()
{
if (!m_console_widget) {
m_console_widget = new Ladybird::ConsoleWidget;
m_console_widget->setWindowTitle("JS Console");
m_console_widget->resize(640, 480);
m_console_widget->on_js_input = [this](auto js_source) {
client().async_js_console_input(js_source);
};
m_console_widget->on_request_messages = [this](i32 start_index) {
client().async_js_console_request_messages(start_index);
};
}
}
void WebContentView::show_js_console()
{
ensure_js_console_widget();
m_console_widget->show();
}
void WebContentView::ensure_inspector_widget()
{
if (m_inspector_widget)
return;
m_inspector_widget = new Ladybird::InspectorWidget;
m_inspector_widget->setWindowTitle("Inspector");
m_inspector_widget->resize(640, 480);
m_inspector_widget->on_close = [this] {
clear_inspected_dom_node();
};
m_inspector_widget->on_dom_node_inspected = [&](auto id, auto pseudo_element) {
return inspect_dom_node(id, pseudo_element);
};
}
void WebContentView::close_sub_widgets()
{
auto close_widget_window = [](auto* widget) {
if (widget)
widget->close();
};
close_widget_window(m_console_widget);
close_widget_window(m_inspector_widget);
}
bool WebContentView::is_inspector_open() const
{
return m_inspector_widget && m_inspector_widget->isVisible();
}
void WebContentView::show_inspector(InspectorTarget inspector_target)
{
bool inspector_previously_loaded = m_inspector_widget;
ensure_inspector_widget();
if (!inspector_previously_loaded || !m_inspector_widget->dom_loaded()) {
inspect_dom_tree();
inspect_accessibility_tree();
}
m_inspector_widget->show();
if (inspector_target == InspectorTarget::HoveredElement) {
auto hovered_node = get_hovered_node_id();
m_inspector_widget->set_selection({ hovered_node });
} else {
m_inspector_widget->select_default_node();
}
}
void WebContentView::update_zoom()
{
client().async_set_device_pixels_per_css_pixel(m_device_pixel_ratio * m_zoom_level);
@ -787,17 +711,11 @@ void WebContentView::notify_server_did_start_loading(Badge<WebContentClient>, AK
{
m_url = url;
emit load_started(url, is_redirect);
if (m_inspector_widget)
m_inspector_widget->clear_dom_json();
}
void WebContentView::notify_server_did_finish_loading(Badge<WebContentClient>, AK::URL const& url)
{
m_url = url;
if (is_inspector_open()) {
inspect_dom_tree();
inspect_accessibility_tree();
}
if (on_load_finish)
on_load_finish(url);
}
@ -903,8 +821,6 @@ void WebContentView::notify_server_did_get_dom_tree(DeprecatedString const& dom_
{
if (on_get_dom_tree)
on_get_dom_tree(dom_tree);
if (m_inspector_widget)
m_inspector_widget->set_dom_json(dom_tree);
}
void WebContentView::notify_server_did_get_dom_node_properties(i32 node_id, DeprecatedString const& specified_style, DeprecatedString const& computed_style, DeprecatedString const& custom_properties, DeprecatedString const& node_box_sizing)
@ -915,14 +831,14 @@ void WebContentView::notify_server_did_get_dom_node_properties(i32 node_id, Depr
void WebContentView::notify_server_did_output_js_console_message(i32 message_index)
{
if (m_console_widget)
m_console_widget->notify_about_new_console_message(message_index);
if (on_js_console_new_message)
on_js_console_new_message(message_index);
}
void WebContentView::notify_server_did_get_js_console_messages(i32 start_index, Vector<DeprecatedString> const& message_types, Vector<DeprecatedString> const& messages)
{
if (m_console_widget)
m_console_widget->handle_console_messages(start_index, message_types, messages);
if (on_get_js_console_messages)
on_get_js_console_messages(start_index, message_types, messages);
}
void WebContentView::notify_server_did_change_favicon(Gfx::Bitmap const& bitmap)
@ -1076,10 +992,10 @@ void WebContentView::notify_server_did_finish_handling_input_event(bool event_wa
(void)event_was_accepted;
}
void WebContentView::notify_server_did_get_accessibility_tree(DeprecatedString const& accessibility_json)
void WebContentView::notify_server_did_get_accessibility_tree(DeprecatedString const& accessibility_tree)
{
if (m_inspector_widget)
m_inspector_widget->set_accessibility_json(accessibility_json);
if (on_get_accessibility_tree)
on_get_accessibility_tree(accessibility_tree);
}
ErrorOr<String> WebContentView::dump_layout_tree()

View file

@ -26,11 +26,6 @@
class QTextEdit;
class QLineEdit;
namespace Ladybird {
class ConsoleWidget;
class InspectorWidget;
}
namespace WebView {
class WebContentClient;
}
@ -66,6 +61,7 @@ public:
Function<void(const AK::URL&, DeprecatedString const&)> on_get_source;
Function<void(DeprecatedString const&)> on_get_dom_tree;
Function<void(i32 node_id, DeprecatedString const& specified_style, DeprecatedString const& computed_style, DeprecatedString const& custom_properties, DeprecatedString const& node_box_sizing)> on_get_dom_node_properties;
Function<void(DeprecatedString const&)> on_get_accessibility_tree;
Function<void(i32 message_id)> on_js_console_new_message;
Function<void(i32 start_index, Vector<DeprecatedString> const& message_types, Vector<DeprecatedString> const& messages)> on_get_js_console_messages;
Function<Vector<Web::Cookie::Cookie>(AK::URL const& url)> on_get_all_cookies;
@ -91,16 +87,6 @@ public:
virtual void focusOutEvent(QFocusEvent*) override;
virtual bool event(QEvent*) override;
void show_js_console();
enum class InspectorTarget {
Document,
HoveredElement
};
void show_inspector(InspectorTarget = InspectorTarget::Document);
Ladybird::ConsoleWidget* console() { return m_console_widget; };
ErrorOr<String> dump_layout_tree();
void set_viewport_rect(Gfx::IntRect);
@ -200,20 +186,11 @@ private:
void update_viewport_rect();
void ensure_js_console_widget();
void ensure_inspector_widget();
bool is_inspector_open() const;
void close_sub_widgets();
qreal m_inverse_pixel_scaling_ratio { 1.0 };
bool m_should_show_line_box_borders { false };
QPointer<QDialog> m_dialog;
Ladybird::ConsoleWidget* m_console_widget { nullptr };
Ladybird::InspectorWidget* m_inspector_widget { nullptr };
Gfx::IntRect m_viewport_rect;
StringView m_webdriver_content_ipc_path;

View file

@ -517,16 +517,6 @@ void OutOfProcessWebView::did_scroll()
request_repaint();
}
void OutOfProcessWebView::js_console_input(DeprecatedString const& js_source)
{
client().async_js_console_input(js_source);
}
void OutOfProcessWebView::js_console_request_messages(i32 start_index)
{
client().async_js_console_request_messages(start_index);
}
DeprecatedString OutOfProcessWebView::dump_layout_tree()
{
return client().dump_layout_tree();

View file

@ -34,9 +34,6 @@ class OutOfProcessWebView final
public:
virtual ~OutOfProcessWebView() override;
void js_console_input(DeprecatedString const& js_source);
void js_console_request_messages(i32 start_index);
DeprecatedString dump_layout_tree();
OrderedHashMap<DeprecatedString, DeprecatedString> get_local_storage_entries();

View file

@ -135,6 +135,16 @@ void ViewImplementation::run_javascript(StringView js_source)
client().async_run_javascript(js_source);
}
void ViewImplementation::js_console_input(DeprecatedString const& js_source)
{
client().async_js_console_input(js_source);
}
void ViewImplementation::js_console_request_messages(i32 start_index)
{
client().async_js_console_request_messages(start_index);
}
void ViewImplementation::toggle_video_play_state()
{
client().async_toggle_video_play_state();

View file

@ -69,6 +69,8 @@ public:
void debug_request(DeprecatedString const& request, DeprecatedString const& argument = {});
void run_javascript(StringView);
void js_console_input(DeprecatedString const& js_source);
void js_console_request_messages(i32 start_index);
void toggle_video_play_state();
void toggle_video_loop_state();