1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 07:47:37 +00:00

Ladybird: Port over part of the "Debug" menu from the SerenityOS browser

This is pretty messy, but we have to start somewhere. Eventually we
should find a way to share this code with SerenityOS.
This commit is contained in:
Andreas Kling 2022-07-08 14:14:40 +02:00 committed by Andrew Kaster
parent eea012472e
commit 487544d7b4
6 changed files with 199 additions and 8 deletions

View file

@ -11,6 +11,8 @@
#include <QAction> #include <QAction>
#include <QStatusBar> #include <QStatusBar>
extern String s_serenity_resource_root;
BrowserWindow::BrowserWindow(Core::EventLoop& event_loop) BrowserWindow::BrowserWindow(Core::EventLoop& event_loop)
: m_event_loop(event_loop) : m_event_loop(event_loop)
{ {
@ -19,16 +21,112 @@ BrowserWindow::BrowserWindow(Core::EventLoop& event_loop)
m_tabs_container->setMovable(true); m_tabs_container->setMovable(true);
m_tabs_container->setTabsClosable(true); m_tabs_container->setTabsClosable(true);
auto* menu = menuBar()->addMenu("File"); auto* menu = menuBar()->addMenu("&File");
auto* new_tab_action = new QAction("New Tab"); auto* new_tab_action = new QAction("New &Tab");
new_tab_action->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_T)); new_tab_action->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_T));
menu->addAction(new_tab_action); menu->addAction(new_tab_action);
auto* quit_action = new QAction("Quit"); auto* quit_action = new QAction("&Quit");
quit_action->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Q)); quit_action->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Q));
menu->addAction(quit_action); menu->addAction(quit_action);
auto* debug_menu = menuBar()->addMenu("&Debug");
auto* dump_dom_tree_action = new QAction("Dump DOM Tree");
dump_dom_tree_action->setIcon(QIcon(QString("%1/res/icons/browser/dom-tree.png").arg(s_serenity_resource_root.characters())));
debug_menu->addAction(dump_dom_tree_action);
QObject::connect(dump_dom_tree_action, &QAction::triggered, this, [this] {
debug_request("dump-dom-tree");
});
auto* dump_layout_tree_action = new QAction("Dump Layout Tree");
dump_layout_tree_action->setIcon(QIcon(QString("%1/res/icons/16x16/layout.png").arg(s_serenity_resource_root.characters())));
debug_menu->addAction(dump_layout_tree_action);
QObject::connect(dump_layout_tree_action, &QAction::triggered, this, [this] {
debug_request("dump-layout-tree");
});
auto* dump_stacking_context_tree_action = new QAction("Dump Stacking Context Tree");
dump_stacking_context_tree_action->setIcon(QIcon(QString("%1/res/icons/16x16/layers.png").arg(s_serenity_resource_root.characters())));
debug_menu->addAction(dump_stacking_context_tree_action);
QObject::connect(dump_stacking_context_tree_action, &QAction::triggered, this, [this] {
debug_request("dump-stacking-context-tree");
});
auto* dump_style_sheets_action = new QAction("Dump Style Sheets");
dump_style_sheets_action->setIcon(QIcon(QString("%1/res/icons/16x16/filetype-css.png").arg(s_serenity_resource_root.characters())));
debug_menu->addAction(dump_style_sheets_action);
QObject::connect(dump_style_sheets_action, &QAction::triggered, this, [this] {
debug_request("dump-style-sheets");
});
auto* dump_history_action = new QAction("Dump History");
dump_history_action->setIcon(QIcon(QString("%1/res/icons/16x16/history.png").arg(s_serenity_resource_root.characters())));
debug_menu->addAction(dump_history_action);
QObject::connect(dump_history_action, &QAction::triggered, this, [this] {
debug_request("dump-history");
});
auto* dump_cookies_action = new QAction("Dump Cookies");
dump_cookies_action->setIcon(QIcon(QString("%1/res/icons/browser/cookie.png").arg(s_serenity_resource_root.characters())));
debug_menu->addAction(dump_cookies_action);
QObject::connect(dump_cookies_action, &QAction::triggered, this, [this] {
debug_request("dump-cookies");
});
auto* dump_local_storage_action = new QAction("Dump Local Storage");
dump_local_storage_action->setIcon(QIcon(QString("%1/res/icons/browser/local-storage.png").arg(s_serenity_resource_root.characters())));
debug_menu->addAction(dump_local_storage_action);
QObject::connect(dump_local_storage_action, &QAction::triggered, this, [this] {
debug_request("dump-local-storage");
});
debug_menu->addSeparator();
auto* show_line_box_borders_action = new QAction("Show Line Box Borders");
show_line_box_borders_action->setCheckable(true);
debug_menu->addAction(show_line_box_borders_action);
QObject::connect(show_line_box_borders_action, &QAction::triggered, this, [this, show_line_box_borders_action] {
bool state = show_line_box_borders_action->isChecked();
debug_request("set-line-box-borders", state ? "on" : "off");
});
debug_menu->addSeparator();
auto* collect_garbage_action = new QAction("Collect Garbage");
collect_garbage_action->setIcon(QIcon(QString("%1/res/icons/16x16/trash-can.png").arg(s_serenity_resource_root.characters())));
debug_menu->addAction(collect_garbage_action);
QObject::connect(collect_garbage_action, &QAction::triggered, this, [this] {
debug_request("collect-garbage");
});
auto* clear_cache_action = new QAction("Clear Cache");
clear_cache_action->setIcon(QIcon(QString("%1/res/icons/browser/clear-cache.png").arg(s_serenity_resource_root.characters())));
debug_menu->addAction(clear_cache_action);
QObject::connect(clear_cache_action, &QAction::triggered, this, [this] {
debug_request("clear-cache");
});
debug_menu->addSeparator();
auto* enable_scripting_action = new QAction("Enable Scripting");
enable_scripting_action->setCheckable(true);
enable_scripting_action->setChecked(true);
debug_menu->addAction(enable_scripting_action);
QObject::connect(enable_scripting_action, &QAction::triggered, this, [this, enable_scripting_action] {
bool state = enable_scripting_action->isChecked();
debug_request("scripting", state ? "on" : "off");
});
auto* enable_same_origin_policy_action = new QAction("Enable Same-Origin Policy");
enable_same_origin_policy_action->setCheckable(true);
debug_menu->addAction(enable_same_origin_policy_action);
QObject::connect(enable_same_origin_policy_action, &QAction::triggered, this, [this, enable_same_origin_policy_action] {
bool state = enable_same_origin_policy_action->isChecked();
debug_request("same-origin-policy", state ? "on" : "off");
});
QObject::connect(new_tab_action, &QAction::triggered, this, &BrowserWindow::new_tab); QObject::connect(new_tab_action, &QAction::triggered, this, &BrowserWindow::new_tab);
QObject::connect(quit_action, &QAction::triggered, this, &QMainWindow::close); QObject::connect(quit_action, &QAction::triggered, this, &QMainWindow::close);
QObject::connect(m_tabs_container, &QTabWidget::currentChanged, [this](int index) { QObject::connect(m_tabs_container, &QTabWidget::currentChanged, [this](int index) {
@ -42,6 +140,13 @@ BrowserWindow::BrowserWindow(Core::EventLoop& event_loop)
setCentralWidget(m_tabs_container); setCentralWidget(m_tabs_container);
} }
void BrowserWindow::debug_request(String const& request, String const& argument)
{
if (!m_current_tab)
return;
m_current_tab->debug_request(request, argument);
}
void BrowserWindow::new_tab() void BrowserWindow::new_tab()
{ {
auto tab = make<Tab>(this); auto tab = make<Tab>(this);

View file

@ -36,6 +36,8 @@ public slots:
void close_tab(int index); void close_tab(int index);
private: private:
void debug_request(String const& request, String const& argument = "");
QTabWidget* m_tabs_container { nullptr }; QTabWidget* m_tabs_container { nullptr };
NonnullOwnPtrVector<Tab> m_tabs; NonnullOwnPtrVector<Tab> m_tabs;
Tab* m_current_tab { nullptr }; Tab* m_current_tab { nullptr };

View file

@ -123,3 +123,8 @@ int Tab::tab_index()
auto browser_window = reinterpret_cast<BrowserWindow*>(m_window); auto browser_window = reinterpret_cast<BrowserWindow*>(m_window);
return browser_window->tab_index(this); return browser_window->tab_index(this);
} }
void Tab::debug_request(String const& request, String const& argument)
{
m_view->debug_request(request, argument);
}

View file

@ -25,6 +25,8 @@ public:
void navigate(QString const&); void navigate(QString const&);
void debug_request(String const& request, String const& argument);
public slots: public slots:
void location_edit_return_pressed(); void location_edit_return_pressed();
void page_title_changed(QString); void page_title_changed(QString);

View file

@ -30,14 +30,19 @@
#include <LibGfx/PNGWriter.h> #include <LibGfx/PNGWriter.h>
#include <LibGfx/Rect.h> #include <LibGfx/Rect.h>
#include <LibMain/Main.h> #include <LibMain/Main.h>
#include <LibWeb/Bindings/MainThreadVM.h>
#include <LibWeb/Cookie/ParsedCookie.h> #include <LibWeb/Cookie/ParsedCookie.h>
#include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/Document.h>
#include <LibWeb/Dump.h>
#include <LibWeb/HTML/BrowsingContext.h> #include <LibWeb/HTML/BrowsingContext.h>
#include <LibWeb/HTML/Storage.h>
#include <LibWeb/HTML/Window.h>
#include <LibWeb/ImageDecoding.h> #include <LibWeb/ImageDecoding.h>
#include <LibWeb/Layout/InitialContainingBlock.h> #include <LibWeb/Layout/InitialContainingBlock.h>
#include <LibWeb/Loader/ResourceLoader.h> #include <LibWeb/Loader/ResourceLoader.h>
#include <LibWeb/Page/Page.h> #include <LibWeb/Page/Page.h>
#include <LibWeb/Painting/PaintableBox.h> #include <LibWeb/Painting/PaintableBox.h>
#include <LibWeb/Painting/StackingContext.h>
#include <LibWeb/WebSockets/WebSocket.h> #include <LibWeb/WebSockets/WebSocket.h>
#include <LibWebSocket/ConnectionInfo.h> #include <LibWebSocket/ConnectionInfo.h>
#include <LibWebSocket/Message.h> #include <LibWebSocket/Message.h>
@ -101,7 +106,7 @@ public:
} }
Web::PaintContext context(painter, palette(), content_rect.top_left()); Web::PaintContext context(painter, palette(), content_rect.top_left());
context.set_should_show_line_box_borders(false); context.set_should_show_line_box_borders(m_should_show_line_box_borders);
context.set_viewport_rect(content_rect); context.set_viewport_rect(content_rect);
context.set_has_focus(true); context.set_has_focus(true);
layout_root->paint_all_phases(context); layout_root->paint_all_phases(context);
@ -279,6 +284,8 @@ public:
request->on_file_request_finish(file); request->on_file_request_finish(file);
} }
void set_should_show_line_box_borders(bool state) { m_should_show_line_box_borders = state; }
private: private:
HeadlessBrowserPageClient(WebView& view) HeadlessBrowserPageClient(WebView& view)
: m_view(view) : m_view(view)
@ -292,6 +299,7 @@ private:
RefPtr<Gfx::PaletteImpl> m_palette_impl; RefPtr<Gfx::PaletteImpl> m_palette_impl;
Gfx::IntRect m_viewport_rect { 0, 0, 800, 600 }; Gfx::IntRect m_viewport_rect { 0, 0, 800, 600 };
Web::CSS::PreferredColorScheme m_preferred_color_scheme { Web::CSS::PreferredColorScheme::Auto }; Web::CSS::PreferredColorScheme m_preferred_color_scheme { Web::CSS::PreferredColorScheme::Auto };
bool m_should_show_line_box_borders { false };
}; };
WebView::WebView() WebView::WebView()
@ -577,12 +585,78 @@ void initialize_web_engine()
Web::WebSockets::WebSocketClientManager::initialize(HeadlessWebSocketClientManager::create()); Web::WebSockets::WebSocketClientManager::initialize(HeadlessWebSocketClientManager::create());
Web::FrameLoader::set_default_favicon_path(String::formatted("{}/res/icons/16x16/app-browser.png", s_serenity_resource_root)); Web::FrameLoader::set_default_favicon_path(String::formatted("{}/res/icons/16x16/app-browser.png", s_serenity_resource_root));
dbgln("Set favoicon path to {}", String::formatted("{}/res/icons/16x16/app-browser.png", s_serenity_resource_root)); dbgln("Set favicon path to {}", String::formatted("{}/res/icons/16x16/app-browser.png", s_serenity_resource_root));
Gfx::FontDatabase::set_default_fonts_lookup_path(String::formatted("{}/res/fonts", s_serenity_resource_root)); // Gfx::FontDatabase::set_default_fonts_lookup_path(String::formatted("{}/res/fonts", s_serenity_resource_root));
Gfx::FontDatabase::set_default_fonts_lookup_path(String::formatted("/home/kling/.local/share/fonts", s_serenity_resource_root));
Gfx::FontDatabase::set_default_font_query("Katica 10 400 0"); Gfx::FontDatabase::set_default_font_query("Calibri 14 400 0");
Gfx::FontDatabase::set_fixed_width_font_query("Csilla 10 400 0"); Gfx::FontDatabase::set_fixed_width_font_query("Consolas 14 400 0");
Web::FrameLoader::set_error_page_url(String::formatted("file://{}/res/html/error.html", s_serenity_resource_root)); Web::FrameLoader::set_error_page_url(String::formatted("file://{}/res/html/error.html", s_serenity_resource_root));
} }
void WebView::debug_request(String const& request, String const& argument)
{
auto& page = m_page_client->page();
if (request == "dump-dom-tree") {
if (auto* doc = page.top_level_browsing_context().active_document())
Web::dump_tree(*doc);
}
if (request == "dump-layout-tree") {
if (auto* doc = page.top_level_browsing_context().active_document()) {
if (auto* icb = doc->layout_node())
Web::dump_tree(*icb);
}
}
if (request == "dump-stacking-context-tree") {
if (auto* doc = page.top_level_browsing_context().active_document()) {
if (auto* icb = doc->layout_node()) {
if (auto* stacking_context = icb->paint_box()->stacking_context())
stacking_context->dump();
}
}
}
if (request == "dump-style-sheets") {
if (auto* doc = page.top_level_browsing_context().active_document()) {
for (auto& sheet : doc->style_sheets().sheets()) {
Web::dump_sheet(sheet);
}
}
}
if (request == "collect-garbage") {
Web::Bindings::main_thread_vm().heap().collect_garbage(JS::Heap::CollectionType::CollectGarbage, true);
}
if (request == "set-line-box-borders") {
bool state = argument == "on";
m_page_client->set_should_show_line_box_borders(state);
page.top_level_browsing_context().set_needs_display(page.top_level_browsing_context().viewport_rect());
}
if (request == "clear-cache") {
Web::ResourceLoader::the().clear_cache();
}
if (request == "spoof-user-agent") {
Web::ResourceLoader::the().set_user_agent(argument);
}
if (request == "same-origin-policy") {
page.set_same_origin_policy_enabled(argument == "on");
}
if (request == "scripting") {
page.set_is_scripting_enabled(argument == "on");
}
if (request == "dump-local-storage") {
if (auto* doc = page.top_level_browsing_context().active_document())
doc->window().local_storage()->dump();
}
}

View file

@ -30,6 +30,8 @@ public:
virtual void mousePressEvent(QMouseEvent*) override; virtual void mousePressEvent(QMouseEvent*) override;
virtual void mouseReleaseEvent(QMouseEvent*) override; virtual void mouseReleaseEvent(QMouseEvent*) override;
void debug_request(String const& request, String const& argument);
signals: signals:
void linkHovered(QString, int timeout = 0); void linkHovered(QString, int timeout = 0);
void linkUnhovered(); void linkUnhovered();
@ -43,4 +45,5 @@ private:
OwnPtr<HeadlessBrowserPageClient> m_page_client; OwnPtr<HeadlessBrowserPageClient> m_page_client;
qreal m_inverse_pixel_scaling_ratio { 1.0 }; qreal m_inverse_pixel_scaling_ratio { 1.0 };
bool m_should_show_line_box_borders { false };
}; };