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 "Utilities.h" | ||||||
| #include "WebContentView.h" | #include "WebContentView.h" | ||||||
| #include <AK/TypeCasts.h> | #include <AK/TypeCasts.h> | ||||||
|  | #include <Browser/CookieJar.h> | ||||||
| #include <LibWeb/Loader/ResourceLoader.h> | #include <LibWeb/Loader/ResourceLoader.h> | ||||||
| #include <QAction> | #include <QAction> | ||||||
| #include <QActionGroup> | #include <QActionGroup> | ||||||
|  | @ -21,8 +22,9 @@ | ||||||
| extern DeprecatedString s_serenity_resource_root; | extern DeprecatedString s_serenity_resource_root; | ||||||
| extern Browser::Settings* s_settings; | extern Browser::Settings* s_settings; | ||||||
| 
 | 
 | ||||||
| BrowserWindow::BrowserWindow(int webdriver_fd_passing_socket) | BrowserWindow::BrowserWindow(Browser::CookieJar& cookie_jar, int webdriver_fd_passing_socket) | ||||||
|     : m_webdriver_fd_passing_socket(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 = new QTabWidget(this); | ||||||
|     m_tabs_container->setElideMode(Qt::TextElideMode::ElideRight); |     m_tabs_container->setElideMode(Qt::TextElideMode::ElideRight); | ||||||
|  |  | ||||||
|  | @ -4,9 +4,10 @@ | ||||||
|  * SPDX-License-Identifier: BSD-2-Clause |  * SPDX-License-Identifier: BSD-2-Clause | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
| #include "Tab.h" | #include "Tab.h" | ||||||
| #include <AK/NonnullOwnPtrVector.h> | #include <AK/NonnullOwnPtrVector.h> | ||||||
| #include <Browser/CookieJar.h> |  | ||||||
| #include <LibCore/Forward.h> | #include <LibCore/Forward.h> | ||||||
| #include <QIcon> | #include <QIcon> | ||||||
| #include <QLineEdit> | #include <QLineEdit> | ||||||
|  | @ -15,14 +16,16 @@ | ||||||
| #include <QTabWidget> | #include <QTabWidget> | ||||||
| #include <QToolBar> | #include <QToolBar> | ||||||
| 
 | 
 | ||||||
| #pragma once |  | ||||||
| 
 |  | ||||||
| class WebContentView; | class WebContentView; | ||||||
| 
 | 
 | ||||||
|  | namespace Browser { | ||||||
|  | class CookieJar; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| class BrowserWindow : public QMainWindow { | class BrowserWindow : public QMainWindow { | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
| public: | 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(); } |     WebContentView& view() const { return m_current_tab->view(); } | ||||||
| 
 | 
 | ||||||
|  | @ -47,7 +50,7 @@ private: | ||||||
|     NonnullOwnPtrVector<Tab> m_tabs; |     NonnullOwnPtrVector<Tab> m_tabs; | ||||||
|     Tab* m_current_tab { nullptr }; |     Tab* m_current_tab { nullptr }; | ||||||
| 
 | 
 | ||||||
|     Browser::CookieJar m_cookie_jar; |     Browser::CookieJar& m_cookie_jar; | ||||||
| 
 | 
 | ||||||
|     int m_webdriver_fd_passing_socket { -1 }; |     int m_webdriver_fd_passing_socket { -1 }; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -67,6 +67,7 @@ set(BROWSER_SOURCE_DIR ${SERENITY_SOURCE_DIR}/Userland/Applications/Browser/) | ||||||
| 
 | 
 | ||||||
| set(SOURCES | set(SOURCES | ||||||
|     ${BROWSER_SOURCE_DIR}/CookieJar.cpp |     ${BROWSER_SOURCE_DIR}/CookieJar.cpp | ||||||
|  |     ${BROWSER_SOURCE_DIR}/Database.cpp | ||||||
|     ${BROWSER_SOURCE_DIR}/History.cpp |     ${BROWSER_SOURCE_DIR}/History.cpp | ||||||
|     BrowserWindow.cpp |     BrowserWindow.cpp | ||||||
|     ConsoleWidget.cpp |     ConsoleWidget.cpp | ||||||
|  | @ -82,7 +83,7 @@ set(SOURCES | ||||||
| qt_add_executable(ladybird ${SOURCES} | qt_add_executable(ladybird ${SOURCES} | ||||||
|     MANUAL_FINALIZATION |     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 ${CMAKE_CURRENT_BINARY_DIR}) | ||||||
| target_include_directories(ladybird PRIVATE ${SERENITY_SOURCE_DIR}/Userland/Applications/) | target_include_directories(ladybird PRIVATE ${SERENITY_SOURCE_DIR}/Userland/Applications/) | ||||||
|  | @ -113,9 +114,10 @@ add_custom_target(debug | ||||||
| 
 | 
 | ||||||
| qt_finalize_executable(ladybird) | qt_finalize_executable(ladybird) | ||||||
| 
 | 
 | ||||||
|  | add_subdirectory(SQLServer) | ||||||
| add_subdirectory(WebContent) | add_subdirectory(WebContent) | ||||||
| add_subdirectory(WebDriver) | add_subdirectory(WebDriver) | ||||||
| add_dependencies(ladybird WebContent WebDriver) | add_dependencies(ladybird SQLServer WebContent WebDriver) | ||||||
| 
 | 
 | ||||||
| if(NOT CMAKE_SKIP_INSTALL_RULES) | if(NOT CMAKE_SKIP_INSTALL_RULES) | ||||||
|     include(cmake/InstallRules.cmake) |     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 "BrowserWindow.h" | ||||||
| #include "Settings.h" | #include "Settings.h" | ||||||
| #include "Utilities.h" | #include "Utilities.h" | ||||||
|  | #include <Browser/CookieJar.h> | ||||||
|  | #include <Browser/Database.h> | ||||||
| #include <LibCore/ArgsParser.h> | #include <LibCore/ArgsParser.h> | ||||||
| #include <LibCore/EventLoop.h> | #include <LibCore/EventLoop.h> | ||||||
| #include <LibCore/File.h> | #include <LibCore/File.h> | ||||||
|  | @ -14,6 +16,7 @@ | ||||||
| #include <LibCore/System.h> | #include <LibCore/System.h> | ||||||
| #include <LibGfx/Font/FontDatabase.h> | #include <LibGfx/Font/FontDatabase.h> | ||||||
| #include <LibMain/Main.h> | #include <LibMain/Main.h> | ||||||
|  | #include <LibSQL/SQLClient.h> | ||||||
| #include <QApplication> | #include <QApplication> | ||||||
| 
 | 
 | ||||||
| Browser::Settings* s_settings; | Browser::Settings* s_settings; | ||||||
|  | @ -44,6 +47,55 @@ static ErrorOr<void> handle_attached_debugger() | ||||||
|     return {}; |     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) | ErrorOr<int> serenity_main(Main::Arguments arguments) | ||||||
| { | { | ||||||
|     // NOTE: This is only used for the Core::Socket inside the IPC connections.
 |     // 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.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); |     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); |     s_settings = new Browser::Settings(&window); | ||||||
|     window.setWindowTitle("Ladybird"); |     window.setWindowTitle("Ladybird"); | ||||||
|     window.resize(800, 600); |     window.resize(800, 600); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Timothy Flynn
						Timothy Flynn