Skip to content

Commit a243bc4

Browse files
committed
Ladybird/Android: Bind a RequestServerService for networking needs
Add a RequestServerService class that uses the LadybirdServiceBase class added previously. Bind to it from the WebContentService's service_main() during startup.
1 parent da8f450 commit a243bc4

15 files changed

+236
-30
lines changed

Ladybird/Android/src/main/AndroidManifest.xml

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
android:smallScreens="true" />
1313

1414
<uses-permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS" />
15+
<uses-permission android:name="android.permission.INTERNET"/>
16+
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
1517

1618
<application
1719
android:allowBackup="true"
@@ -28,27 +30,32 @@
2830
android:supportsRtl="true"
2931
android:theme="@style/Theme.Ladybird"
3032
tools:targetApi="33">
31-
3233
<activity
3334
android:name=".LadybirdActivity"
3435
android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density"
3536
android:exported="true"
36-
android:label="@string/app_name"
3737
android:launchMode="singleTop"
3838
android:screenOrientation="unspecified">
3939
<intent-filter>
4040
<action android:name="android.intent.action.MAIN" />
41+
4142
<category android:name="android.intent.category.LAUNCHER" />
4243
</intent-filter>
44+
4345
<meta-data
4446
android:name="android.app.extract_android_style"
4547
android:value="minimal" />
4648
</activity>
47-
4849
<service
4950
android:name=".WebContentService"
51+
android:enabled="true"
52+
android:exported="false"
53+
android:process=":WebContent" />
54+
<service
55+
android:name=".RequestServerService"
56+
android:enabled="true"
5057
android:exported="false"
51-
android:process=":WebContent"/>
58+
android:process=":RequestServer" />
5259
</application>
5360

5461
</manifest>

Ladybird/Android/src/main/cpp/LadybirdServiceBase.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,8 @@
77
#pragma once
88

99
#include <AK/Error.h>
10+
#include <jni.h>
1011

1112
ErrorOr<int> service_main(int ipc_socket, int fd_passing_socket);
13+
14+
extern JavaVM* global_vm;

Ladybird/Android/src/main/cpp/LadybirdServiceBaseJNI.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#include <Ladybird/Utilities.h>
1111
#include <jni.h>
1212

13+
JavaVM* global_vm;
14+
1315
extern "C" JNIEXPORT void JNICALL
1416
Java_org_serenityos_ladybird_LadybirdServiceBase_nativeThreadLoop(JNIEnv*, jobject /* thiz */, jint ipc_socket, jint fd_passing_socket)
1517
{
@@ -31,6 +33,8 @@ Java_org_serenityos_ladybird_LadybirdServiceBase_initNativeCode(JNIEnv* env, job
3133
return;
3234
}
3335

36+
env->GetJavaVM(&global_vm);
37+
3438
char const* raw_resource_dir = env->GetStringUTFChars(resource_dir, nullptr);
3539
s_serenity_resource_root = raw_resource_dir;
3640
env->ReleaseStringUTFChars(resource_dir, raw_resource_dir);
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
3+
* Copyright (c) 2023, Andrew Kaster <akaster@serenityos.org>
4+
*
5+
* SPDX-License-Identifier: BSD-2-Clause
6+
*/
7+
8+
#include <AK/LexicalPath.h>
9+
#include <AK/OwnPtr.h>
10+
#include <Ladybird/Utilities.h>
11+
#include <LibCore/ArgsParser.h>
12+
#include <LibCore/EventLoop.h>
13+
#include <LibCore/LocalServer.h>
14+
#include <LibCore/System.h>
15+
#include <LibFileSystem/FileSystem.h>
16+
#include <LibIPC/SingleServer.h>
17+
#include <LibTLS/Certificate.h>
18+
#include <RequestServer/ConnectionFromClient.h>
19+
#include <RequestServer/GeminiProtocol.h>
20+
#include <RequestServer/HttpProtocol.h>
21+
#include <RequestServer/HttpsProtocol.h>
22+
23+
// FIXME: Share b/w RequestServer and WebSocket
24+
ErrorOr<String> find_certificates(StringView serenity_resource_root)
25+
{
26+
auto cert_path = TRY(String::formatted("{}/res/ladybird/cacert.pem", serenity_resource_root));
27+
if (!FileSystem::exists(cert_path)) {
28+
auto app_dir = LexicalPath::dirname(TRY(Core::System::current_executable_path()).to_deprecated_string());
29+
30+
cert_path = TRY(String::formatted("{}/cacert.pem", LexicalPath(app_dir).parent()));
31+
if (!FileSystem::exists(cert_path))
32+
return Error::from_string_view("Don't know how to load certs!"sv);
33+
}
34+
return cert_path;
35+
}
36+
37+
ErrorOr<int> service_main(int ipc_socket, int fd_passing_socket)
38+
{
39+
// Ensure the certificates are read out here.
40+
DefaultRootCACertificates::set_default_certificate_path(TRY(find_certificates(s_serenity_resource_root)));
41+
[[maybe_unused]] auto& certs = DefaultRootCACertificates::the();
42+
43+
Core::EventLoop event_loop;
44+
45+
// FIXME: Don't leak these :V
46+
[[maybe_unused]] auto* gemini = new RequestServer::GeminiProtocol;
47+
[[maybe_unused]] auto* http = new RequestServer::HttpProtocol;
48+
[[maybe_unused]] auto* https = new RequestServer::HttpsProtocol;
49+
50+
auto socket = TRY(Core::LocalSocket::adopt_fd(ipc_socket));
51+
auto client = TRY(RequestServer::ConnectionFromClient::try_create(move(socket)));
52+
client->set_fd_passing_socket(TRY(Core::LocalSocket::adopt_fd(fd_passing_socket)));
53+
54+
return event_loop.exec();
55+
}

Ladybird/Android/src/main/cpp/WebContentService.cpp

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* SPDX-License-Identifier: BSD-2-Clause
55
*/
66

7+
#include "WebContentService.h"
78
#include "LadybirdServiceBase.h"
89
#include <AK/LexicalPath.h>
910
#include <Ladybird/FontPlugin.h>
@@ -28,15 +29,7 @@
2829
#include <WebContent/ConnectionFromClient.h>
2930
#include <WebContent/PageHost.h>
3031

31-
class NullResourceConnector : public Web::ResourceLoaderConnector {
32-
virtual void prefetch_dns(AK::URL const&) override { }
33-
virtual void preconnect(AK::URL const&) override { }
34-
35-
virtual RefPtr<Web::ResourceLoaderConnectorRequest> start_request(DeprecatedString const&, AK::URL const&, HashMap<DeprecatedString, DeprecatedString> const&, ReadonlyBytes, Core::ProxyData const&) override
36-
{
37-
return nullptr;
38-
}
39-
};
32+
static ErrorOr<NonnullRefPtr<Protocol::RequestClient>> bind_request_server_service();
4033

4134
ErrorOr<int> service_main(int ipc_socket, int fd_passing_socket)
4235
{
@@ -52,7 +45,8 @@ ErrorOr<int> service_main(int ipc_socket, int fd_passing_socket)
5245

5346
Web::FrameLoader::set_default_favicon_path(DeprecatedString::formatted("{}/res/icons/16x16/app-browser.png", s_serenity_resource_root));
5447

55-
Web::ResourceLoader::initialize(make_ref_counted<NullResourceConnector>());
48+
auto request_server_client = TRY(bind_request_server_service());
49+
Web::ResourceLoader::initialize(TRY(WebView::RequestServerAdapter::try_create(move(request_server_client))));
5650

5751
bool is_layout_test_mode = false;
5852

@@ -71,3 +65,29 @@ ErrorOr<int> service_main(int ipc_socket, int fd_passing_socket)
7165

7266
return event_loop.exec();
7367
}
68+
69+
ErrorOr<NonnullRefPtr<Protocol::RequestClient>> bind_request_server_service()
70+
{
71+
int socket_fds[2] {};
72+
TRY(Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, socket_fds));
73+
74+
int ui_fd = socket_fds[0];
75+
int server_fd = socket_fds[1];
76+
77+
int fd_passing_socket_fds[2] {};
78+
TRY(Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, fd_passing_socket_fds));
79+
80+
int ui_fd_passing_fd = fd_passing_socket_fds[0];
81+
int server_fd_passing_fd = fd_passing_socket_fds[1];
82+
83+
// NOTE: The java object takes ownership of the socket fds
84+
bind_request_server_java(server_fd, server_fd_passing_fd);
85+
86+
auto socket = TRY(Core::LocalSocket::adopt_fd(ui_fd));
87+
TRY(socket->set_blocking(true));
88+
89+
auto new_client = TRY(try_make_ref_counted<Protocol::RequestClient>(move(socket)));
90+
new_client->set_fd_passing_socket(TRY(Core::LocalSocket::adopt_fd(ui_fd_passing_fd)));
91+
92+
return new_client;
93+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/*
2+
* Copyright (c) 2023, Andrew Kaster <akaster@serenityos.org>
3+
*
4+
* SPDX-License-Identifier: BSD-2-Clause
5+
*/
6+
7+
#pragma once
8+
9+
void bind_request_server_java(int ipc_socket, int fd_passing_socket);
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright (c) 2023, Andrew Kaster <akaster@serenityos.org>
3+
*
4+
* SPDX-License-Identifier: BSD-2-Clause
5+
*/
6+
7+
#include "JNIHelpers.h"
8+
#include "LadybirdServiceBase.h"
9+
#include <jni.h>
10+
11+
jobject global_instance;
12+
jclass global_class_reference;
13+
jmethodID bind_request_server_method;
14+
15+
extern "C" JNIEXPORT void JNICALL
16+
Java_org_serenityos_ladybird_WebContentService_nativeInit(JNIEnv* env, jobject thiz)
17+
{
18+
global_instance = env->NewGlobalRef(thiz);
19+
20+
auto local_class = env->FindClass("org/serenityos/ladybird/WebContentService");
21+
if (!local_class)
22+
TODO();
23+
global_class_reference = reinterpret_cast<jclass>(env->NewGlobalRef(local_class));
24+
env->DeleteLocalRef(local_class);
25+
26+
auto method = env->GetMethodID(global_class_reference, "bindRequestServer", "(II)V");
27+
if (!method)
28+
TODO();
29+
bind_request_server_method = method;
30+
}
31+
32+
void bind_request_server_java(int ipc_socket, int fd_passing_socket)
33+
{
34+
JavaEnvironment env(global_vm);
35+
env.get()->CallVoidMethod(global_instance, bind_request_server_method, ipc_socket, fd_passing_socket);
36+
}

Ladybird/Android/src/main/java/org/serenityos/ladybird/LadybirdActivity.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ package org.serenityos.ladybird
99
import androidx.appcompat.app.AppCompatActivity
1010
import android.os.Bundle
1111
import org.serenityos.ladybird.databinding.ActivityMainBinding
12+
import java.net.URL
1213
import kotlin.io.path.Path
1314

1415
class LadybirdActivity : AppCompatActivity() {
@@ -37,7 +38,7 @@ class LadybirdActivity : AppCompatActivity() {
3738
super.onStart()
3839

3940
// FIXME: This is not the right place to load the homepage :^)
40-
val initialURL = Path(resourceDir, "res/html/misc/welcome.html").toUri().toURL()
41+
val initialURL = URL("https://ladybird.dev")
4142
view.loadURL(initialURL)
4243
}
4344

Ladybird/Android/src/main/java/org/serenityos/ladybird/LadybirdServiceBase.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const val MSG_TRANSFER_SOCKETS = 2
2323

2424
abstract class LadybirdServiceBase(protected val TAG: String) : Service() {
2525
private val threadPool = Executors.newCachedThreadPool()
26-
private lateinit var resourceDir: String
26+
protected lateinit var resourceDir: String
2727

2828
override fun onCreate() {
2929
super.onCreate()
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* Copyright (c) 2023, Andrew Kaster <akaster@serenityos.org>
3+
*
4+
* SPDX-License-Identifier: BSD-2-Clause
5+
*/
6+
7+
package org.serenityos.ladybird
8+
9+
import android.os.Message
10+
11+
class RequestServerService : LadybirdServiceBase("RequestServerService") {
12+
override fun handleServiceSpecificMessage(msg: Message): Boolean {
13+
return false
14+
}
15+
16+
companion object {
17+
init {
18+
System.loadLibrary("requestserver")
19+
}
20+
}
21+
}

0 commit comments

Comments
 (0)