LibWebView+UI: Launch the DevTools server if --devtools is specified

This replaces the --devtools-port flag with a --devtools flag, which
optionally accepts a port. If the --devtools flag is set, we will now
automatically launch the DevTools server.
This commit is contained in:
Timothy Flynn 2025-07-02 12:42:53 -04:00 committed by Tim Flynn
commit b55d2909f6
Notes: github-actions[bot] 2025-07-02 19:29:12 +00:00
5 changed files with 43 additions and 11 deletions

View file

@ -5,10 +5,10 @@ with the DevTools client.
## Using DevTools
The DevTools server may be enabled in the "Inspect" menu via the "Enable DevTools" menu item. A banner will be displayed
in Ladybird with the port on which the DevTools server is listening. This port may be changed with the `--devtools-port`
command line flag. To disable DevTools, use the same menu item (which will now be titled "Disable DevTools"), or close
the banner.
The DevTools server may be enabled in the "Inspect" menu via the "Enable DevTools" menu item, or with the `--devtools`
command line flag. A banner will be displayed in Ladybird with the port on which the DevTools server is listening. This
port may be changed by providing a port to the command line flag, e.g. `--devtools=6001`. To disable DevTools, use the
menu item (which will now be titled "Disable DevTools"), or close the banner.
Once DevTools is enabled, in Firefox, navigate to `about:debugging` and select the "Setup" tab. In the "Network Location"
form, enter the DevTools server address. In the above example, this will be `localhost:6000`. You will only have to

View file

@ -101,7 +101,7 @@ ErrorOr<void> Application::initialize(Main::Arguments const& arguments)
bool allow_popups = false;
bool disable_scripting = false;
bool disable_sql_database = false;
u16 devtools_port = WebView::default_devtools_port;
Optional<u16> devtools_port;
Optional<StringView> debug_process;
Optional<StringView> profile_process;
Optional<StringView> webdriver_content_ipc_path;
@ -157,7 +157,6 @@ ErrorOr<void> Application::initialize(Main::Arguments const& arguments)
args_parser.add_option(debug_process, "Wait for a debugger to attach to the given process name (WebContent, RequestServer, etc.)", "debug-process", 0, "process-name");
args_parser.add_option(profile_process, "Enable callgrind profiling of the given process name (WebContent, RequestServer, etc.)", "profile-process", 0, "process-name");
args_parser.add_option(webdriver_content_ipc_path, "Path to WebDriver IPC for WebContent", "webdriver-content-path", 0, "path", Core::ArgsParser::OptionHideMode::CommandLineAndMarkdown);
args_parser.add_option(devtools_port, "Set the Firefox DevTools server port ", "devtools-port", 0, "port");
args_parser.add_option(layout_test_mode, "Enable layout test mode", "layout-test-mode");
args_parser.add_option(log_all_js_exceptions, "Log all JavaScript exceptions", "log-all-js-exceptions");
args_parser.add_option(disable_site_isolation, "Disable site isolation", "disable-site-isolation");
@ -174,6 +173,21 @@ ErrorOr<void> Application::initialize(Main::Arguments const& arguments)
args_parser.add_option(use_dns_over_tls, "Use DNS over TLS", "dot");
args_parser.add_option(validate_dnssec_locally, "Validate DNSSEC locally", "dnssec");
args_parser.add_option(Core::ArgsParser::Option {
.argument_mode = Core::ArgsParser::OptionArgumentMode::Optional,
.help_string = "Enable the Firefox DevTools server, with an optional port",
.long_name = "devtools",
.value_name = "port",
.accept_value = [&](StringView value) {
if (value.is_empty())
devtools_port = WebView::default_devtools_port;
else
devtools_port = value.to_number<u16>();
return devtools_port.has_value();
},
});
args_parser.add_option(Core::ArgsParser::Option {
.argument_mode = Core::ArgsParser::OptionArgumentMode::Required,
.help_string = "Name of the User-Agent preset to use in place of the default User-Agent",
@ -350,6 +364,10 @@ ErrorOr<void> Application::launch_services()
TRY(launch_request_server());
TRY(launch_image_decoder_server());
if (m_browser_options.devtools_port.has_value())
TRY(launch_devtools_server());
return {};
}
@ -395,7 +413,11 @@ ErrorOr<void> Application::launch_image_decoder_server()
ErrorOr<void> Application::launch_devtools_server()
{
VERIFY(!m_devtools);
m_devtools = TRY(DevTools::DevToolsServer::create(*this, m_browser_options.devtools_port));
if (!m_browser_options.devtools_port.has_value())
m_browser_options.devtools_port = WebView::default_devtools_port;
m_devtools = TRY(DevTools::DevToolsServer::create(*this, *m_browser_options.devtools_port));
return {};
}

View file

@ -84,7 +84,7 @@ struct BrowserOptions {
Optional<ProcessType> profile_helper_process {};
Optional<ByteString> webdriver_content_ipc_path {};
Optional<DNSSettings> dns_settings {};
u16 devtools_port { default_devtools_port };
Optional<u16> devtools_port;
};
enum class IsLayoutTestMode {

View file

@ -753,9 +753,14 @@
- (void)applicationDidFinishLaunching:(NSNotification*)notification
{
auto const& browser_options = WebView::Application::browser_options();
if (browser_options.devtools_port.has_value())
[self devtoolsEnabled];
Tab* tab = nil;
for (auto const& url : WebView::Application::browser_options().urls) {
for (auto const& url : browser_options.urls) {
auto activate_tab = tab == nil ? Web::HTML::ActivateTab::Yes : Web::HTML::ActivateTab::No;
auto* controller = [self createNewTab:url

View file

@ -75,6 +75,8 @@ BrowserWindow::BrowserWindow(Vector<URL::URL> const& initial_urls, IsPopupWindow
, m_new_tab_button_toolbar(new QToolBar("New Tab", m_tabs_container))
, m_is_popup_window(is_popup_window)
{
auto const& browser_options = WebView::Application::browser_options();
setWindowIcon(app_icon());
// Listen for DPI changes
@ -549,7 +551,7 @@ BrowserWindow::BrowserWindow(Vector<URL::URL> const& initial_urls, IsPopupWindow
m_enable_scripting_action = new QAction("Enable Scripting", this);
m_enable_scripting_action->setCheckable(true);
m_enable_scripting_action->setChecked(WebView::Application::browser_options().disable_scripting == WebView::DisableScripting::No);
m_enable_scripting_action->setChecked(browser_options.disable_scripting == WebView::DisableScripting::No);
debug_menu->addAction(m_enable_scripting_action);
QObject::connect(m_enable_scripting_action, &QAction::triggered, this, [this] {
bool state = m_enable_scripting_action->isChecked();
@ -571,7 +573,7 @@ BrowserWindow::BrowserWindow(Vector<URL::URL> const& initial_urls, IsPopupWindow
m_block_pop_ups_action = new QAction("Block Pop-ups", this);
m_block_pop_ups_action->setCheckable(true);
m_block_pop_ups_action->setChecked(WebView::Application::browser_options().allow_popups == WebView::AllowPopups::No);
m_block_pop_ups_action->setChecked(browser_options.allow_popups == WebView::AllowPopups::No);
debug_menu->addAction(m_block_pop_ups_action);
QObject::connect(m_block_pop_ups_action, &QAction::triggered, this, [this] {
bool state = m_block_pop_ups_action->isChecked();
@ -683,6 +685,9 @@ BrowserWindow::BrowserWindow(Vector<URL::URL> const& initial_urls, IsPopupWindow
setCentralWidget(m_tabs_container);
setContextMenuPolicy(Qt::PreventContextMenu);
if (browser_options.devtools_port.has_value())
devtools_enabled();
}
void BrowserWindow::devtools_disabled()