diff --git a/Ladybird/Android/src/main/AndroidManifest.xml b/Ladybird/Android/src/main/AndroidManifest.xml
index c48a1e683a6..7fe1232bdd7 100644
--- a/Ladybird/Android/src/main/AndroidManifest.xml
+++ b/Ladybird/Android/src/main/AndroidManifest.xml
@@ -12,6 +12,8 @@
android:smallScreens="true" />
+
+
-
+
+
-
+ android:process=":WebContent" />
+
diff --git a/Ladybird/Android/src/main/cpp/LadybirdServiceBase.h b/Ladybird/Android/src/main/cpp/LadybirdServiceBase.h
index 1879f9a201d..a30ab0f09e2 100644
--- a/Ladybird/Android/src/main/cpp/LadybirdServiceBase.h
+++ b/Ladybird/Android/src/main/cpp/LadybirdServiceBase.h
@@ -7,5 +7,8 @@
#pragma once
#include
+#include
ErrorOr service_main(int ipc_socket, int fd_passing_socket);
+
+extern JavaVM* global_vm;
diff --git a/Ladybird/Android/src/main/cpp/LadybirdServiceBaseJNI.cpp b/Ladybird/Android/src/main/cpp/LadybirdServiceBaseJNI.cpp
index 3a7c12bc73f..cbd1d7d4a05 100644
--- a/Ladybird/Android/src/main/cpp/LadybirdServiceBaseJNI.cpp
+++ b/Ladybird/Android/src/main/cpp/LadybirdServiceBaseJNI.cpp
@@ -10,6 +10,8 @@
#include
#include
+JavaVM* global_vm;
+
extern "C" JNIEXPORT void JNICALL
Java_org_serenityos_ladybird_LadybirdServiceBase_nativeThreadLoop(JNIEnv*, jobject /* thiz */, jint ipc_socket, jint fd_passing_socket)
{
@@ -31,6 +33,8 @@ Java_org_serenityos_ladybird_LadybirdServiceBase_initNativeCode(JNIEnv* env, job
return;
}
+ env->GetJavaVM(&global_vm);
+
char const* raw_resource_dir = env->GetStringUTFChars(resource_dir, nullptr);
s_serenity_resource_root = raw_resource_dir;
env->ReleaseStringUTFChars(resource_dir, raw_resource_dir);
diff --git a/Ladybird/Android/src/main/cpp/RequestServerService.cpp b/Ladybird/Android/src/main/cpp/RequestServerService.cpp
new file mode 100644
index 00000000000..3856e2670e9
--- /dev/null
+++ b/Ladybird/Android/src/main/cpp/RequestServerService.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling
+ * Copyright (c) 2023, Andrew Kaster
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// FIXME: Share b/w RequestServer and WebSocket
+ErrorOr find_certificates(StringView serenity_resource_root)
+{
+ auto cert_path = TRY(String::formatted("{}/res/ladybird/cacert.pem", serenity_resource_root));
+ if (!FileSystem::exists(cert_path)) {
+ auto app_dir = LexicalPath::dirname(TRY(Core::System::current_executable_path()).to_deprecated_string());
+
+ cert_path = TRY(String::formatted("{}/cacert.pem", LexicalPath(app_dir).parent()));
+ if (!FileSystem::exists(cert_path))
+ return Error::from_string_view("Don't know how to load certs!"sv);
+ }
+ return cert_path;
+}
+
+ErrorOr service_main(int ipc_socket, int fd_passing_socket)
+{
+ // Ensure the certificates are read out here.
+ DefaultRootCACertificates::set_default_certificate_path(TRY(find_certificates(s_serenity_resource_root)));
+ [[maybe_unused]] auto& certs = DefaultRootCACertificates::the();
+
+ Core::EventLoop event_loop;
+
+ // FIXME: Don't leak these :V
+ [[maybe_unused]] auto* gemini = new RequestServer::GeminiProtocol;
+ [[maybe_unused]] auto* http = new RequestServer::HttpProtocol;
+ [[maybe_unused]] auto* https = new RequestServer::HttpsProtocol;
+
+ auto socket = TRY(Core::LocalSocket::adopt_fd(ipc_socket));
+ auto client = TRY(RequestServer::ConnectionFromClient::try_create(move(socket)));
+ client->set_fd_passing_socket(TRY(Core::LocalSocket::adopt_fd(fd_passing_socket)));
+
+ return event_loop.exec();
+}
diff --git a/Ladybird/Android/src/main/cpp/WebContentService.cpp b/Ladybird/Android/src/main/cpp/WebContentService.cpp
index 919c707f6af..4fd80d2c6c3 100644
--- a/Ladybird/Android/src/main/cpp/WebContentService.cpp
+++ b/Ladybird/Android/src/main/cpp/WebContentService.cpp
@@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
+#include "WebContentService.h"
#include "LadybirdServiceBase.h"
#include
#include
@@ -28,15 +29,7 @@
#include
#include
-class NullResourceConnector : public Web::ResourceLoaderConnector {
- virtual void prefetch_dns(AK::URL const&) override { }
- virtual void preconnect(AK::URL const&) override { }
-
- virtual RefPtr start_request(DeprecatedString const&, AK::URL const&, HashMap const&, ReadonlyBytes, Core::ProxyData const&) override
- {
- return nullptr;
- }
-};
+static ErrorOr> bind_request_server_service();
ErrorOr service_main(int ipc_socket, int fd_passing_socket)
{
@@ -52,7 +45,8 @@ ErrorOr service_main(int ipc_socket, int fd_passing_socket)
Web::FrameLoader::set_default_favicon_path(DeprecatedString::formatted("{}/res/icons/16x16/app-browser.png", s_serenity_resource_root));
- Web::ResourceLoader::initialize(make_ref_counted());
+ auto request_server_client = TRY(bind_request_server_service());
+ Web::ResourceLoader::initialize(TRY(WebView::RequestServerAdapter::try_create(move(request_server_client))));
bool is_layout_test_mode = false;
@@ -71,3 +65,29 @@ ErrorOr service_main(int ipc_socket, int fd_passing_socket)
return event_loop.exec();
}
+
+ErrorOr> bind_request_server_service()
+{
+ int socket_fds[2] {};
+ TRY(Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, socket_fds));
+
+ int ui_fd = socket_fds[0];
+ int server_fd = socket_fds[1];
+
+ int fd_passing_socket_fds[2] {};
+ TRY(Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, fd_passing_socket_fds));
+
+ int ui_fd_passing_fd = fd_passing_socket_fds[0];
+ int server_fd_passing_fd = fd_passing_socket_fds[1];
+
+ // NOTE: The java object takes ownership of the socket fds
+ bind_request_server_java(server_fd, server_fd_passing_fd);
+
+ auto socket = TRY(Core::LocalSocket::adopt_fd(ui_fd));
+ TRY(socket->set_blocking(true));
+
+ auto new_client = TRY(try_make_ref_counted(move(socket)));
+ new_client->set_fd_passing_socket(TRY(Core::LocalSocket::adopt_fd(ui_fd_passing_fd)));
+
+ return new_client;
+}
diff --git a/Ladybird/Android/src/main/cpp/WebContentService.h b/Ladybird/Android/src/main/cpp/WebContentService.h
new file mode 100644
index 00000000000..2da6a1c0c93
--- /dev/null
+++ b/Ladybird/Android/src/main/cpp/WebContentService.h
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2023, Andrew Kaster
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+void bind_request_server_java(int ipc_socket, int fd_passing_socket);
diff --git a/Ladybird/Android/src/main/cpp/WebContentServiceJNI.cpp b/Ladybird/Android/src/main/cpp/WebContentServiceJNI.cpp
new file mode 100644
index 00000000000..111e3940f78
--- /dev/null
+++ b/Ladybird/Android/src/main/cpp/WebContentServiceJNI.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2023, Andrew Kaster
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include "JNIHelpers.h"
+#include "LadybirdServiceBase.h"
+#include
+
+jobject global_instance;
+jclass global_class_reference;
+jmethodID bind_request_server_method;
+
+extern "C" JNIEXPORT void JNICALL
+Java_org_serenityos_ladybird_WebContentService_nativeInit(JNIEnv* env, jobject thiz)
+{
+ global_instance = env->NewGlobalRef(thiz);
+
+ auto local_class = env->FindClass("org/serenityos/ladybird/WebContentService");
+ if (!local_class)
+ TODO();
+ global_class_reference = reinterpret_cast(env->NewGlobalRef(local_class));
+ env->DeleteLocalRef(local_class);
+
+ auto method = env->GetMethodID(global_class_reference, "bindRequestServer", "(II)V");
+ if (!method)
+ TODO();
+ bind_request_server_method = method;
+}
+
+void bind_request_server_java(int ipc_socket, int fd_passing_socket)
+{
+ JavaEnvironment env(global_vm);
+ env.get()->CallVoidMethod(global_instance, bind_request_server_method, ipc_socket, fd_passing_socket);
+}
diff --git a/Ladybird/Android/src/main/java/org/serenityos/ladybird/LadybirdActivity.kt b/Ladybird/Android/src/main/java/org/serenityos/ladybird/LadybirdActivity.kt
index de5eeb5debf..84c57622640 100644
--- a/Ladybird/Android/src/main/java/org/serenityos/ladybird/LadybirdActivity.kt
+++ b/Ladybird/Android/src/main/java/org/serenityos/ladybird/LadybirdActivity.kt
@@ -9,6 +9,7 @@ package org.serenityos.ladybird
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import org.serenityos.ladybird.databinding.ActivityMainBinding
+import java.net.URL
import kotlin.io.path.Path
class LadybirdActivity : AppCompatActivity() {
@@ -37,7 +38,7 @@ class LadybirdActivity : AppCompatActivity() {
super.onStart()
// FIXME: This is not the right place to load the homepage :^)
- val initialURL = Path(resourceDir, "res/html/misc/welcome.html").toUri().toURL()
+ val initialURL = URL("https://ladybird.dev")
view.loadURL(initialURL)
}
diff --git a/Ladybird/Android/src/main/java/org/serenityos/ladybird/LadybirdServiceBase.kt b/Ladybird/Android/src/main/java/org/serenityos/ladybird/LadybirdServiceBase.kt
index 15d28c66392..f3f9d27a9d6 100644
--- a/Ladybird/Android/src/main/java/org/serenityos/ladybird/LadybirdServiceBase.kt
+++ b/Ladybird/Android/src/main/java/org/serenityos/ladybird/LadybirdServiceBase.kt
@@ -23,7 +23,7 @@ const val MSG_TRANSFER_SOCKETS = 2
abstract class LadybirdServiceBase(protected val TAG: String) : Service() {
private val threadPool = Executors.newCachedThreadPool()
- private lateinit var resourceDir: String
+ protected lateinit var resourceDir: String
override fun onCreate() {
super.onCreate()
diff --git a/Ladybird/Android/src/main/java/org/serenityos/ladybird/RequestServerService.kt b/Ladybird/Android/src/main/java/org/serenityos/ladybird/RequestServerService.kt
new file mode 100644
index 00000000000..c1941a38b88
--- /dev/null
+++ b/Ladybird/Android/src/main/java/org/serenityos/ladybird/RequestServerService.kt
@@ -0,0 +1,21 @@
+/**
+ * Copyright (c) 2023, Andrew Kaster
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+package org.serenityos.ladybird
+
+import android.os.Message
+
+class RequestServerService : LadybirdServiceBase("RequestServerService") {
+ override fun handleServiceSpecificMessage(msg: Message): Boolean {
+ return false
+ }
+
+ companion object {
+ init {
+ System.loadLibrary("requestserver")
+ }
+ }
+}
diff --git a/Ladybird/Android/src/main/java/org/serenityos/ladybird/WebContentService.kt b/Ladybird/Android/src/main/java/org/serenityos/ladybird/WebContentService.kt
index 5b7c9fd670c..3c531baa35c 100644
--- a/Ladybird/Android/src/main/java/org/serenityos/ladybird/WebContentService.kt
+++ b/Ladybird/Android/src/main/java/org/serenityos/ladybird/WebContentService.kt
@@ -6,13 +6,37 @@
package org.serenityos.ladybird
+import android.content.Context
+import android.content.Intent
import android.os.Message
+import android.util.Log
class WebContentService : LadybirdServiceBase("WebContentService") {
override fun handleServiceSpecificMessage(msg: Message): Boolean {
return false
}
+ init {
+ nativeInit();
+ }
+
+ private fun bindRequestServer(ipcFd: Int, fdPassingFd: Int)
+ {
+ val connector = LadybirdServiceConnection(ipcFd, fdPassingFd, resourceDir)
+ connector.onDisconnect = {
+ // FIXME: Notify impl that service is dead and might need restarted
+ Log.e(TAG, "RequestServer Died! :(")
+ }
+ // FIXME: Unbind this at some point maybe
+ bindService(
+ Intent(this, RequestServerService::class.java),
+ connector,
+ Context.BIND_AUTO_CREATE
+ )
+ }
+
+ external fun nativeInit()
+
companion object {
init {
System.loadLibrary("webcontent")
diff --git a/Ladybird/RequestServer/CMakeLists.txt b/Ladybird/RequestServer/CMakeLists.txt
index fab905c34c3..3b6f4e94e53 100644
--- a/Ladybird/RequestServer/CMakeLists.txt
+++ b/Ladybird/RequestServer/CMakeLists.txt
@@ -1,5 +1,9 @@
set(REQUESTSERVER_SOURCE_DIR ${SERENITY_SOURCE_DIR}/Userland/Services/RequestServer)
+set(CMAKE_AUTOMOC OFF)
+set(CMAKE_AUTORCC OFF)
+set(CMAKE_AUTOUIC OFF)
+
set(REQUESTSERVER_SOURCES
${REQUESTSERVER_SOURCE_DIR}/ConnectionFromClient.cpp
${REQUESTSERVER_SOURCE_DIR}/ConnectionCache.cpp
@@ -11,17 +15,28 @@ set(REQUESTSERVER_SOURCES
${REQUESTSERVER_SOURCE_DIR}/HttpsRequest.cpp
${REQUESTSERVER_SOURCE_DIR}/HttpsProtocol.cpp
${REQUESTSERVER_SOURCE_DIR}/Protocol.cpp
- main.cpp
)
-add_executable(RequestServer ${REQUESTSERVER_SOURCES})
+if (ANDROID)
+ add_library(requestserver SHARED
+ ${REQUESTSERVER_SOURCES}
+ ../Android/src/main/cpp/RequestServerService.cpp
+ ../Android/src/main/cpp/LadybirdServiceBaseJNI.cpp
+ ../Utilities.cpp
+ )
+else()
+ add_library(requestserver STATIC ${REQUESTSERVER_SOURCES})
+endif()
-target_include_directories(RequestServer PRIVATE ${SERENITY_SOURCE_DIR}/Userland/Services/)
-target_include_directories(RequestServer PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/..)
-target_link_libraries(RequestServer PRIVATE LibCore LibMain LibCrypto LibFileSystem LibGemini LibHTTP LibIPC LibMain LibTLS LibWebView)
+add_executable(RequestServer main.cpp)
+target_link_libraries(RequestServer PRIVATE requestserver)
+
+target_include_directories(requestserver PRIVATE ${SERENITY_SOURCE_DIR}/Userland/Services/)
+target_include_directories(requestserver PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/..)
+target_link_libraries(requestserver PUBLIC LibCore LibMain LibCrypto LibFileSystem LibGemini LibHTTP LibIPC LibMain LibTLS LibWebView)
if (${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
# Solaris has socket and networking related functions in two extra libraries
- target_link_libraries(RequestServer PRIVATE nsl socket)
+ target_link_libraries(requestserver PUBLIC nsl socket)
endif()
if (HAIKU)
# Haiku has networking related functions in the network library
diff --git a/Ladybird/WebContent/CMakeLists.txt b/Ladybird/WebContent/CMakeLists.txt
index 20c131dd72e..bc12a8ee108 100644
--- a/Ladybird/WebContent/CMakeLists.txt
+++ b/Ladybird/WebContent/CMakeLists.txt
@@ -55,6 +55,7 @@ else()
if (ANDROID)
target_sources(webcontent PRIVATE
../Android/src/main/cpp/WebContentService.cpp
+ ../Android/src/main/cpp/WebContentServiceJNI.cpp
../Android/src/main/cpp/LadybirdServiceBaseJNI.cpp
)
target_link_libraries(webcontent PRIVATE android)
diff --git a/Ladybird/cmake/AndroidExtras.cmake b/Ladybird/cmake/AndroidExtras.cmake
index cc137bd6ea1..672ccc98ad7 100644
--- a/Ladybird/cmake/AndroidExtras.cmake
+++ b/Ladybird/cmake/AndroidExtras.cmake
@@ -33,7 +33,12 @@ add_custom_target(copy-content-filters
"${SERENITY_SOURCE_DIR}/Base/home/anon/.config/BrowserContentFilters.txt"
"asset-bundle/res/ladybird/BrowserContentFilters.txt"
)
-add_dependencies(archive-assets copy-autoplay-allowlist copy-content-filters)
+add_custom_target(copy-certs
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ "${Lagom_BINARY_DIR}/cacert.pem"
+ "asset-bundle/res/ladybird/cacert.pem"
+)
+add_dependencies(archive-assets copy-autoplay-allowlist copy-content-filters copy-certs)
add_custom_target(copy-assets COMMAND ${CMAKE_COMMAND} -E copy_if_different ladybird-assets.tar.gz "${CMAKE_SOURCE_DIR}/Android/src/main/assets/")
add_dependencies(copy-assets archive-assets)
add_dependencies(ladybird copy-assets)
diff --git a/Ladybird/cmake/InstallRules.cmake b/Ladybird/cmake/InstallRules.cmake
index c428b17fbca..9bb811bfb38 100644
--- a/Ladybird/cmake/InstallRules.cmake
+++ b/Ladybird/cmake/InstallRules.cmake
@@ -36,13 +36,18 @@ list(REMOVE_DUPLICATES all_required_lagom_libraries)
# Remove ladybird shlib if it exists
list(REMOVE_ITEM all_required_lagom_libraries ladybird)
-# Install webcontent impl library if it exists
-if (TARGET webcontent)
- get_target_property(target_type webcontent TYPE)
- if ("${target_type}" STREQUAL STATIC_LIBRARY)
- list(APPEND all_required_lagom_libraries webcontent)
- endif()
-endif()
+# Install service impl libraries if they exist
+macro(install_service_lib service)
+ if (TARGET ${service})
+ get_target_property(target_type ${service} TYPE)
+ if ("${target_type}" STREQUAL STATIC_LIBRARY)
+ list(APPEND all_required_lagom_libraries ${service})
+ endif()
+ endif()
+endmacro()
+foreach(service IN LISTS webcontent requestserver)
+ install_service_lib(${service})
+endforeach()
install(TARGETS ${all_required_lagom_libraries}
EXPORT ladybirdTargets