Skip to content

Commit da8f450

Browse files
committed
Ladybird/Android: Move common service functionality to a base class
Create LadybirdServiceBase to hold the standard "set resource dir" and "init ipc sockets" service functionality that will be common between the WebContent, RequestServer, and WebSocket services. Refactor the handler class slightly to avoid the HandlerLeak lint by making the class a static class inside the companion object and use a WeakReference to the service instead of a strong one.
1 parent 315ad2d commit da8f450

File tree

8 files changed

+117
-91
lines changed

8 files changed

+117
-91
lines changed

Ladybird/Android/src/main/cpp/WebContentService.h renamed to Ladybird/Android/src/main/cpp/LadybirdServiceBase.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@
88

99
#include <AK/Error.h>
1010

11-
ErrorOr<int> web_content_main(int ipc_socket, int fd_passing_socket);
11+
ErrorOr<int> service_main(int ipc_socket, int fd_passing_socket);

Ladybird/Android/src/main/cpp/WebContentServiceJNI.cpp renamed to Ladybird/Android/src/main/cpp/LadybirdServiceBaseJNI.cpp

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

7-
#include "WebContentService.h"
7+
#include "LadybirdServiceBase.h"
88
#include <AK/Atomic.h>
99
#include <AK/Format.h>
1010
#include <Ladybird/Utilities.h>
1111
#include <jni.h>
1212

1313
extern "C" JNIEXPORT void JNICALL
14-
Java_org_serenityos_ladybird_WebContentService_nativeThreadLoop(JNIEnv*, jobject /* thiz */, jint ipc_socket, jint fd_passing_socket)
14+
Java_org_serenityos_ladybird_LadybirdServiceBase_nativeThreadLoop(JNIEnv*, jobject /* thiz */, jint ipc_socket, jint fd_passing_socket)
1515
{
1616
dbgln("New binding received, sockets {} and {}", ipc_socket, fd_passing_socket);
17-
auto ret = web_content_main(ipc_socket, fd_passing_socket);
17+
auto ret = service_main(ipc_socket, fd_passing_socket);
1818
if (ret.is_error()) {
1919
warnln("Runtime Error: {}", ret.release_error());
2020
} else {
@@ -23,7 +23,7 @@ Java_org_serenityos_ladybird_WebContentService_nativeThreadLoop(JNIEnv*, jobject
2323
}
2424

2525
extern "C" JNIEXPORT void JNICALL
26-
Java_org_serenityos_ladybird_WebContentService_initNativeCode(JNIEnv* env, jobject /* thiz */, jstring resource_dir, jstring tag_name)
26+
Java_org_serenityos_ladybird_LadybirdServiceBase_initNativeCode(JNIEnv* env, jobject /* thiz */, jstring resource_dir, jstring tag_name)
2727
{
2828
static Atomic<bool> s_initialized_flag { false };
2929
if (s_initialized_flag.exchange(true) == true) {

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

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

7-
#include "WebContentService.h"
7+
#include "LadybirdServiceBase.h"
88
#include <AK/LexicalPath.h>
99
#include <Ladybird/FontPlugin.h>
1010
#include <Ladybird/HelperProcess.h>
@@ -38,7 +38,7 @@ class NullResourceConnector : public Web::ResourceLoaderConnector {
3838
}
3939
};
4040

41-
ErrorOr<int> web_content_main(int ipc_socket, int fd_passing_socket)
41+
ErrorOr<int> service_main(int ipc_socket, int fd_passing_socket)
4242
{
4343
Core::EventLoop event_loop;
4444

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
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.app.Service
10+
import android.content.Intent
11+
import android.util.Log
12+
import android.os.ParcelFileDescriptor
13+
import android.os.Handler
14+
import android.os.IBinder
15+
import android.os.Looper
16+
import android.os.Message
17+
import android.os.Messenger
18+
import java.lang.ref.WeakReference
19+
import java.util.concurrent.Executors
20+
21+
const val MSG_SET_RESOURCE_ROOT = 1
22+
const val MSG_TRANSFER_SOCKETS = 2
23+
24+
abstract class LadybirdServiceBase(protected val TAG: String) : Service() {
25+
private val threadPool = Executors.newCachedThreadPool()
26+
private lateinit var resourceDir: String
27+
28+
override fun onCreate() {
29+
super.onCreate()
30+
Log.i(TAG, "Creating Service")
31+
}
32+
33+
override fun onDestroy() {
34+
super.onDestroy()
35+
Log.i(TAG, "Destroying Service")
36+
}
37+
38+
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
39+
Log.i(TAG, "Start command received")
40+
return super.onStartCommand(intent, flags, startId)
41+
}
42+
43+
private fun handleTransferSockets(msg: Message) {
44+
val bundle = msg.data
45+
// FIXME: Handle garbage messages from wierd clients
46+
val ipcSocket = bundle.getParcelable<ParcelFileDescriptor>("IPC_SOCKET")!!
47+
val fdSocket = bundle.getParcelable<ParcelFileDescriptor>("FD_PASSING_SOCKET")!!
48+
createThread(ipcSocket, fdSocket)
49+
}
50+
51+
private fun handleSetResourceRoot(msg: Message) {
52+
// FIXME: Handle this being already set, not being present, etc
53+
resourceDir = msg.data.getString("PATH")!!
54+
55+
initNativeCode(resourceDir, TAG)
56+
}
57+
58+
override fun onBind(p0: Intent?): IBinder? {
59+
// FIXME: Check the intent to make sure it's legit
60+
return Messenger(IncomingHandler(WeakReference(this))).binder
61+
}
62+
63+
64+
private fun createThread(ipcSocket: ParcelFileDescriptor, fdSocket: ParcelFileDescriptor) {
65+
threadPool.execute {
66+
nativeThreadLoop(ipcSocket.detachFd(), fdSocket.detachFd())
67+
}
68+
}
69+
70+
private external fun nativeThreadLoop(ipcSocket: Int, fdPassingSocket: Int)
71+
private external fun initNativeCode(resourceDir: String, tagName: String);
72+
73+
abstract fun handleServiceSpecificMessage(msg: Message): Boolean
74+
75+
companion object {
76+
77+
class IncomingHandler(private val service: WeakReference<LadybirdServiceBase>) :
78+
Handler(Looper.getMainLooper()) {
79+
override fun handleMessage(msg: Message) {
80+
when (msg.what) {
81+
MSG_TRANSFER_SOCKETS -> service.get()?.handleTransferSockets(msg)
82+
?: super.handleMessage(msg)
83+
84+
MSG_SET_RESOURCE_ROOT -> service.get()?.handleSetResourceRoot(msg)
85+
?: super.handleMessage(msg)
86+
87+
else -> {
88+
val ret = service.get()?.handleServiceSpecificMessage(msg)
89+
if (ret == null || !ret)
90+
super.handleMessage(msg)
91+
}
92+
}
93+
}
94+
}
95+
}
96+
}

Ladybird/Android/src/main/java/org/serenityos/ladybird/WebContentServiceConnection.kt renamed to Ladybird/Android/src/main/java/org/serenityos/ladybird/LadybirdServiceConnection.kt

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,40 +13,40 @@ import android.os.Message
1313
import android.os.Messenger
1414
import android.os.ParcelFileDescriptor
1515

16-
class WebContentServiceConnection(
16+
class LadybirdServiceConnection(
1717
private var ipcFd: Int,
1818
private var fdPassingFd: Int,
1919
private var resourceDir: String
2020
) :
2121
ServiceConnection {
22-
var boundToWebContent: Boolean = false
22+
var boundToService: Boolean = false
2323
var onDisconnect: () -> Unit = {}
24-
private var webContentService: Messenger? = null
24+
private var service: Messenger? = null
2525

2626
override fun onServiceConnected(className: ComponentName, svc: IBinder) {
2727
// This is called when the connection with the service has been
2828
// established, giving us the object we can use to
2929
// interact with the service. We are communicating with the
3030
// service using a Messenger, so here we get a client-side
3131
// representation of that from the raw IBinder object.
32-
webContentService = Messenger(svc)
33-
boundToWebContent = true
32+
service = Messenger(svc)
33+
boundToService = true
3434

3535
val init = Message.obtain(null, MSG_SET_RESOURCE_ROOT)
3636
init.data.putString("PATH", resourceDir)
37-
webContentService!!.send(init)
37+
service!!.send(init)
3838

3939
val msg = Message.obtain(null, MSG_TRANSFER_SOCKETS)
4040
msg.data.putParcelable("IPC_SOCKET", ParcelFileDescriptor.adoptFd(ipcFd))
4141
msg.data.putParcelable("FD_PASSING_SOCKET", ParcelFileDescriptor.adoptFd(fdPassingFd))
42-
webContentService!!.send(msg)
42+
service!!.send(msg)
4343
}
4444

4545
override fun onServiceDisconnected(className: ComponentName) {
4646
// This is called when the connection with the service has been
4747
// unexpectedly disconnected; that is, its process crashed.
48-
webContentService = null
49-
boundToWebContent = false
48+
service = null
49+
boundToService = false
5050

5151
// Notify owner that the service is dead
5252
onDisconnect()

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

Lines changed: 3 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -6,83 +6,13 @@
66

77
package org.serenityos.ladybird
88

9-
import android.app.Service
10-
import android.content.Intent
11-
import android.util.Log
12-
import android.os.ParcelFileDescriptor
13-
import android.os.Handler
14-
import android.os.IBinder
159
import android.os.Message
16-
import android.os.Messenger
17-
import java.util.concurrent.Executors
1810

19-
const val MSG_SET_RESOURCE_ROOT = 1
20-
const val MSG_TRANSFER_SOCKETS = 2
21-
22-
class WebContentService : Service() {
23-
private val TAG = "WebContentService"
24-
25-
private val threadPool = Executors.newCachedThreadPool()
26-
private lateinit var resourceDir: String
27-
28-
override fun onCreate() {
29-
super.onCreate()
30-
Log.i(TAG, "Creating Service")
31-
}
32-
33-
override fun onDestroy() {
34-
super.onDestroy()
35-
Log.i(TAG, "Destroying Service")
36-
}
37-
38-
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
39-
Log.i(TAG, "Start command received")
40-
return super.onStartCommand(intent, flags, startId)
41-
}
42-
43-
private fun handleTransferSockets(msg: Message) {
44-
val bundle = msg.data
45-
// FIXME: Handle garbage messages from wierd clients
46-
val ipcSocket = bundle.getParcelable<ParcelFileDescriptor>("IPC_SOCKET")!!
47-
val fdSocket = bundle.getParcelable<ParcelFileDescriptor>("FD_PASSING_SOCKET")!!
48-
createThread(ipcSocket, fdSocket)
49-
}
50-
51-
private fun handleSetResourceRoot(msg: Message) {
52-
// FIXME: Handle this being already set, not being present, etc
53-
resourceDir = msg.data.getString("PATH")!!
54-
55-
initNativeCode(resourceDir, TAG)
56-
}
57-
58-
internal class IncomingHandler(
59-
context: WebContentService,
60-
private val owner: WebContentService = context
61-
) : Handler() {
62-
override fun handleMessage(msg: Message) {
63-
when (msg.what) {
64-
MSG_TRANSFER_SOCKETS -> this.owner.handleTransferSockets(msg)
65-
MSG_SET_RESOURCE_ROOT -> this.owner.handleSetResourceRoot(msg)
66-
else -> super.handleMessage(msg)
67-
}
68-
}
69-
}
70-
71-
override fun onBind(p0: Intent?): IBinder? {
72-
// FIXME: Check the intent to make sure it's legit
73-
return Messenger(IncomingHandler(this)).binder
11+
class WebContentService : LadybirdServiceBase("WebContentService") {
12+
override fun handleServiceSpecificMessage(msg: Message): Boolean {
13+
return false
7414
}
7515

76-
private external fun nativeThreadLoop(ipcSocket: Int, fdPassingSocket: Int)
77-
78-
private fun createThread(ipcSocket: ParcelFileDescriptor, fdSocket: ParcelFileDescriptor) {
79-
threadPool.execute {
80-
nativeThreadLoop(ipcSocket.detachFd(), fdSocket.detachFd())
81-
}
82-
}
83-
84-
private external fun initNativeCode(resourceDir: String, tagName: String);
85-
8616
companion object {
8717
init {
8818
System.loadLibrary("webcontent")

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class WebViewImplementation(private val view: WebView) {
5151

5252
// Functions called from native code
5353
fun bindWebContentService(ipcFd: Int, fdPassingFd: Int) {
54-
val connector = WebContentServiceConnection(ipcFd, fdPassingFd, resourceDir)
54+
val connector = LadybirdServiceConnection(ipcFd, fdPassingFd, resourceDir)
5555
connector.onDisconnect = {
5656
// FIXME: Notify impl that service is dead and might need restarted
5757
Log.e("WebContentView", "WebContent Died! :(")

Ladybird/WebContent/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ else()
5555
if (ANDROID)
5656
target_sources(webcontent PRIVATE
5757
../Android/src/main/cpp/WebContentService.cpp
58-
../Android/src/main/cpp/WebContentServiceJNI.cpp
58+
../Android/src/main/cpp/LadybirdServiceBaseJNI.cpp
5959
)
6060
target_link_libraries(webcontent PRIVATE android)
6161
endif()

0 commit comments

Comments
 (0)