mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 16:22:43 +00:00 
			
		
		
		
	Ladybird: Implement SQLServer for Ladybird :^)
This adds a SQLServer binary for Ladybird to make use of Serenity's SQL implementation. This has to use the same IPC socket handling that was used to make WebContent and WebDriver work out-of-process. Unlike Serenity, Ladybird creates a new SQLServer instance for each Ladybird instance. In the future, we should try to make sure there is only one SQLServer instance at a time, and allow multiple Ladybird instances to communicate with it.
This commit is contained in:
		
							parent
							
								
									a0cd260410
								
							
						
					
					
						commit
						2cb3ae132a
					
				
					 6 changed files with 127 additions and 10 deletions
				
			
		|  | @ -12,6 +12,7 @@ | |||
| #include "Utilities.h" | ||||
| #include "WebContentView.h" | ||||
| #include <AK/TypeCasts.h> | ||||
| #include <Browser/CookieJar.h> | ||||
| #include <LibWeb/Loader/ResourceLoader.h> | ||||
| #include <QAction> | ||||
| #include <QActionGroup> | ||||
|  | @ -21,8 +22,9 @@ | |||
| extern DeprecatedString s_serenity_resource_root; | ||||
| extern Browser::Settings* s_settings; | ||||
| 
 | ||||
| BrowserWindow::BrowserWindow(int webdriver_fd_passing_socket) | ||||
|     : m_webdriver_fd_passing_socket(webdriver_fd_passing_socket) | ||||
| BrowserWindow::BrowserWindow(Browser::CookieJar& cookie_jar, int webdriver_fd_passing_socket) | ||||
|     : m_cookie_jar(cookie_jar) | ||||
|     , m_webdriver_fd_passing_socket(webdriver_fd_passing_socket) | ||||
| { | ||||
|     m_tabs_container = new QTabWidget(this); | ||||
|     m_tabs_container->setElideMode(Qt::TextElideMode::ElideRight); | ||||
|  |  | |||
|  | @ -4,9 +4,10 @@ | |||
|  * SPDX-License-Identifier: BSD-2-Clause | ||||
|  */ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include "Tab.h" | ||||
| #include <AK/NonnullOwnPtrVector.h> | ||||
| #include <Browser/CookieJar.h> | ||||
| #include <LibCore/Forward.h> | ||||
| #include <QIcon> | ||||
| #include <QLineEdit> | ||||
|  | @ -15,14 +16,16 @@ | |||
| #include <QTabWidget> | ||||
| #include <QToolBar> | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| class WebContentView; | ||||
| 
 | ||||
| namespace Browser { | ||||
| class CookieJar; | ||||
| } | ||||
| 
 | ||||
| class BrowserWindow : public QMainWindow { | ||||
|     Q_OBJECT | ||||
| public: | ||||
|     explicit BrowserWindow(int webdriver_fd_passing_socket); | ||||
|     explicit BrowserWindow(Browser::CookieJar&, int webdriver_fd_passing_socket); | ||||
| 
 | ||||
|     WebContentView& view() const { return m_current_tab->view(); } | ||||
| 
 | ||||
|  | @ -47,7 +50,7 @@ private: | |||
|     NonnullOwnPtrVector<Tab> m_tabs; | ||||
|     Tab* m_current_tab { nullptr }; | ||||
| 
 | ||||
|     Browser::CookieJar m_cookie_jar; | ||||
|     Browser::CookieJar& m_cookie_jar; | ||||
| 
 | ||||
|     int m_webdriver_fd_passing_socket { -1 }; | ||||
| }; | ||||
|  |  | |||
|  | @ -67,6 +67,7 @@ set(BROWSER_SOURCE_DIR ${SERENITY_SOURCE_DIR}/Userland/Applications/Browser/) | |||
| 
 | ||||
| set(SOURCES | ||||
|     ${BROWSER_SOURCE_DIR}/CookieJar.cpp | ||||
|     ${BROWSER_SOURCE_DIR}/Database.cpp | ||||
|     ${BROWSER_SOURCE_DIR}/History.cpp | ||||
|     BrowserWindow.cpp | ||||
|     ConsoleWidget.cpp | ||||
|  | @ -82,7 +83,7 @@ set(SOURCES | |||
| qt_add_executable(ladybird ${SOURCES} | ||||
|     MANUAL_FINALIZATION | ||||
| ) | ||||
| target_link_libraries(ladybird PRIVATE Qt::Core Qt::Gui Qt::Network Qt::Widgets LibCore LibGfx LibGUI LibIPC LibJS LibMain LibWeb LibWebView) | ||||
| target_link_libraries(ladybird PRIVATE Qt::Core Qt::Gui Qt::Network Qt::Widgets LibCore LibGfx LibGUI LibIPC LibJS LibMain LibWeb LibWebView LibSQL) | ||||
| 
 | ||||
| target_include_directories(ladybird PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) | ||||
| target_include_directories(ladybird PRIVATE ${SERENITY_SOURCE_DIR}/Userland/Applications/) | ||||
|  | @ -113,9 +114,10 @@ add_custom_target(debug | |||
| 
 | ||||
| qt_finalize_executable(ladybird) | ||||
| 
 | ||||
| add_subdirectory(SQLServer) | ||||
| add_subdirectory(WebContent) | ||||
| add_subdirectory(WebDriver) | ||||
| add_dependencies(ladybird WebContent WebDriver) | ||||
| add_dependencies(ladybird SQLServer WebContent WebDriver) | ||||
| 
 | ||||
| if(NOT CMAKE_SKIP_INSTALL_RULES) | ||||
|     include(cmake/InstallRules.cmake) | ||||
|  |  | |||
							
								
								
									
										14
									
								
								Ladybird/SQLServer/CMakeLists.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								Ladybird/SQLServer/CMakeLists.txt
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,14 @@ | |||
| set(SQL_SERVER_SOURCE_DIR ${SERENITY_SOURCE_DIR}/Userland/Services/SQLServer) | ||||
| 
 | ||||
| set(SQL_SERVER_SOURCES | ||||
|     ${SQL_SERVER_SOURCE_DIR}/ConnectionFromClient.cpp | ||||
|     ${SQL_SERVER_SOURCE_DIR}/DatabaseConnection.cpp | ||||
|     ${SQL_SERVER_SOURCE_DIR}/SQLStatement.cpp | ||||
|     main.cpp | ||||
| ) | ||||
| 
 | ||||
| qt_add_executable(SQLServer ${SQL_SERVER_SOURCES}) | ||||
| 
 | ||||
| target_include_directories(SQLServer PRIVATE ${SERENITY_SOURCE_DIR}/Userland/Services/) | ||||
| target_include_directories(SQLServer PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/..) | ||||
| target_link_libraries(SQLServer PRIVATE Qt::Core Qt::Gui Qt::Network LibCore LibIPC LibSQL LibMain) | ||||
							
								
								
									
										41
									
								
								Ladybird/SQLServer/main.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								Ladybird/SQLServer/main.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,41 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org> | ||||
|  * | ||||
|  * SPDX-License-Identifier: BSD-2-Clause | ||||
|  */ | ||||
| 
 | ||||
| #define AK_DONT_REPLACE_STD | ||||
| 
 | ||||
| #include <AK/DeprecatedString.h> | ||||
| #include <LibCore/ArgsParser.h> | ||||
| #include <LibCore/Directory.h> | ||||
| #include <LibCore/EventLoop.h> | ||||
| #include <LibCore/StandardPaths.h> | ||||
| #include <LibCore/Stream.h> | ||||
| #include <LibCore/SystemServerTakeover.h> | ||||
| #include <LibMain/Main.h> | ||||
| #include <QSocketNotifier> | ||||
| #include <SQLServer/ConnectionFromClient.h> | ||||
| 
 | ||||
| ErrorOr<int> serenity_main(Main::Arguments arguments) | ||||
| { | ||||
|     int sql_server_fd_passing_socket { -1 }; | ||||
| 
 | ||||
|     Core::ArgsParser args_parser; | ||||
|     args_parser.add_option(sql_server_fd_passing_socket, "File descriptor of the passing socket for the SQLServer connection", "sql-server-fd-passing-socket", 's', "sql_server_fd_passing_socket"); | ||||
|     args_parser.parse(arguments); | ||||
| 
 | ||||
|     VERIFY(sql_server_fd_passing_socket >= 0); | ||||
| 
 | ||||
|     auto database_path = DeprecatedString::formatted("{}/Ladybird", Core::StandardPaths::data_directory()); | ||||
|     TRY(Core::Directory::create(database_path, Core::Directory::CreateDirectories::Yes)); | ||||
| 
 | ||||
|     Core::EventLoop loop; | ||||
| 
 | ||||
|     auto socket = TRY(Core::take_over_socket_from_system_server("SQLServer"sv)); | ||||
|     auto client = TRY(SQLServer::ConnectionFromClient::try_create(move(socket), 1)); | ||||
|     client->set_fd_passing_socket(TRY(Core::Stream::LocalSocket::adopt_fd(sql_server_fd_passing_socket))); | ||||
|     client->set_database_path(move(database_path)); | ||||
| 
 | ||||
|     return loop.exec(); | ||||
| } | ||||
|  | @ -7,6 +7,8 @@ | |||
| #include "BrowserWindow.h" | ||||
| #include "Settings.h" | ||||
| #include "Utilities.h" | ||||
| #include <Browser/CookieJar.h> | ||||
| #include <Browser/Database.h> | ||||
| #include <LibCore/ArgsParser.h> | ||||
| #include <LibCore/EventLoop.h> | ||||
| #include <LibCore/File.h> | ||||
|  | @ -14,6 +16,7 @@ | |||
| #include <LibCore/System.h> | ||||
| #include <LibGfx/Font/FontDatabase.h> | ||||
| #include <LibMain/Main.h> | ||||
| #include <LibSQL/SQLClient.h> | ||||
| #include <QApplication> | ||||
| 
 | ||||
| Browser::Settings* s_settings; | ||||
|  | @ -44,6 +47,55 @@ static ErrorOr<void> handle_attached_debugger() | |||
|     return {}; | ||||
| } | ||||
| 
 | ||||
| ErrorOr<NonnullRefPtr<Browser::Database>> create_database() | ||||
| { | ||||
|     int socket_fds[2] {}; | ||||
|     TRY(Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, socket_fds)); | ||||
|     auto [browser_fd, sql_server_fd] = socket_fds; | ||||
| 
 | ||||
|     int fd_passing_socket_fds[2] {}; | ||||
|     TRY(Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, fd_passing_socket_fds)); | ||||
|     auto [browser_fd_passing_fd, sql_server_fd_passing_fd] = fd_passing_socket_fds; | ||||
| 
 | ||||
|     auto sql_server_pid = TRY(Core::System::fork()); | ||||
| 
 | ||||
|     if (sql_server_pid == 0) { | ||||
|         TRY(Core::System::close(browser_fd_passing_fd)); | ||||
|         TRY(Core::System::close(browser_fd)); | ||||
| 
 | ||||
|         DeprecatedString takeover_string; | ||||
|         if (auto* socket_takeover = getenv("SOCKET_TAKEOVER")) | ||||
|             takeover_string = DeprecatedString::formatted("{} SQLServer:{}", socket_takeover, sql_server_fd); | ||||
|         else | ||||
|             takeover_string = DeprecatedString::formatted("SQLServer:{}", sql_server_fd); | ||||
|         TRY(Core::System::setenv("SOCKET_TAKEOVER"sv, takeover_string, true)); | ||||
| 
 | ||||
|         auto sql_server_fd_passing_fd_string = DeprecatedString::number(sql_server_fd_passing_fd); | ||||
| 
 | ||||
|         char const* argv[] = { | ||||
|             "SQLServer", | ||||
|             "--sql-server-fd-passing-socket", | ||||
|             sql_server_fd_passing_fd_string.characters(), | ||||
|             nullptr, | ||||
|         }; | ||||
| 
 | ||||
|         if (execvp("./SQLServer/SQLServer", const_cast<char**>(argv)) < 0) | ||||
|             perror("execvp"); | ||||
|         VERIFY_NOT_REACHED(); | ||||
|     } | ||||
| 
 | ||||
|     TRY(Core::System::close(sql_server_fd_passing_fd)); | ||||
|     TRY(Core::System::close(sql_server_fd)); | ||||
| 
 | ||||
|     auto socket = TRY(Core::Stream::LocalSocket::adopt_fd(browser_fd)); | ||||
|     TRY(socket->set_blocking(true)); | ||||
| 
 | ||||
|     auto sql_client = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) SQL::SQLClient(std::move(socket)))); | ||||
|     sql_client->set_fd_passing_socket(TRY(Core::Stream::LocalSocket::adopt_fd(browser_fd_passing_fd))); | ||||
| 
 | ||||
|     return Browser::Database::create(move(sql_client)); | ||||
| } | ||||
| 
 | ||||
| ErrorOr<int> serenity_main(Main::Arguments arguments) | ||||
| { | ||||
|     // NOTE: This is only used for the Core::Socket inside the IPC connections.
 | ||||
|  | @ -69,7 +121,10 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) | |||
|     args_parser.add_option(webdriver_fd_passing_socket, "File descriptor of the passing socket for the WebDriver connection", "webdriver-fd-passing-socket", 'd', "webdriver_fd_passing_socket"); | ||||
|     args_parser.parse(arguments); | ||||
| 
 | ||||
|     BrowserWindow window(webdriver_fd_passing_socket); | ||||
|     auto database = TRY(create_database()); | ||||
|     auto cookie_jar = TRY(Browser::CookieJar::create(*database)); | ||||
| 
 | ||||
|     BrowserWindow window(cookie_jar, webdriver_fd_passing_socket); | ||||
|     s_settings = new Browser::Settings(&window); | ||||
|     window.setWindowTitle("Ladybird"); | ||||
|     window.resize(800, 600); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Timothy Flynn
						Timothy Flynn