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:
parent
eea012472e
commit
487544d7b4
6 changed files with 199 additions and 8 deletions
|
@ -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);
|
||||||
|
|
|
@ -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 };
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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 };
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue