Skip to content

Commit 2463927

Browse files
committed
Simplify message handling APIs
1 parent 39fa7dc commit 2463927

File tree

7 files changed

+84
-57
lines changed

7 files changed

+84
-57
lines changed

app/src/androidTest/java/com/duckduckgo/app/browser/BrowserWebViewClientTest.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ import com.duckduckgo.duckplayer.api.DuckPlayer.OpenDuckPlayerInNewTab.On
8888
import com.duckduckgo.duckplayer.api.DuckPlayer.OpenDuckPlayerInNewTab.Unavailable
8989
import com.duckduckgo.feature.toggles.api.Toggle
9090
import com.duckduckgo.history.api.NavigationHistory
91-
import com.duckduckgo.js.messaging.api.JsMessageCallback
91+
import com.duckduckgo.js.messaging.api.WebViewCompatMessageCallback
9292
import com.duckduckgo.privacy.config.api.AmpLinks
9393
import com.duckduckgo.subscriptions.api.Subscriptions
9494
import com.duckduckgo.user.agent.api.ClientBrandHintProvider
@@ -353,7 +353,7 @@ class BrowserWebViewClientTest {
353353
@Test
354354
fun whenConfigureWebViewThenInjectJsCode() {
355355
assertEquals(0, fakeAddDocumentStartJavaScriptPlugins.plugin.countInitted)
356-
val mockCallback = mock<JsMessageCallback>()
356+
val mockCallback = mock<WebViewCompatMessageCallback>()
357357
testee.configureWebView(DuckDuckGoWebView(context), mockCallback)
358358
assertEquals(1, fakeAddDocumentStartJavaScriptPlugins.plugin.countInitted)
359359
}
@@ -362,15 +362,15 @@ class BrowserWebViewClientTest {
362362
@Test
363363
fun whenConfigureWebViewThenAddWebMessageListener() {
364364
assertFalse(fakeMessagingPlugins.plugin.registered)
365-
val mockCallback = mock<JsMessageCallback>()
365+
val mockCallback = mock<WebViewCompatMessageCallback>()
366366
testee.configureWebView(DuckDuckGoWebView(context), mockCallback)
367367
assertTrue(fakeMessagingPlugins.plugin.registered)
368368
}
369369

370370
@UiThreadTest
371371
@Test
372372
fun whenDestroyThenRemoveWebMessageListener() = runTest {
373-
val mockCallback = mock<JsMessageCallback>()
373+
val mockCallback = mock<WebViewCompatMessageCallback>()
374374
val webView = DuckDuckGoWebView(context)
375375
testee.configureWebView(webView, mockCallback)
376376
assertTrue(fakeMessagingPlugins.plugin.registered)
@@ -1345,7 +1345,7 @@ class BrowserWebViewClientTest {
13451345
}
13461346

13471347
override suspend fun register(
1348-
jsMessageCallback: JsMessageCallback?,
1348+
jsMessageCallback: WebViewCompatMessageCallback?,
13491349
registerer: suspend (objectName: String, allowedOriginRules: Set<String>, webMessageListener: WebMessageListener) -> Boolean,
13501350
) {
13511351
registered = true

content-scope-scripts/content-scope-scripts-api/src/main/java/com/duckduckgo/contentscopescripts/api/GlobalContentScopeJsMessageHandlersPlugin.kt

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@
1717
package com.duckduckgo.contentscopescripts.api
1818

1919
import com.duckduckgo.js.messaging.api.JsMessage
20-
import com.duckduckgo.js.messaging.api.WebViewCompatMessageCallback
21-
import org.json.JSONObject
20+
import com.duckduckgo.js.messaging.api.WebViewCompatMessageHandler.ProcessResult
2221

2322
/**
2423
* Plugin interface for global message handlers that should always be processed
@@ -45,13 +44,10 @@ interface GlobalJsMessageHandler {
4544
* invoking a callback so consumers can also process the message if needed.
4645
*
4746
* @param jsMessage The JavaScript message to be processed.
48-
* @param jsMessageCallback An optional callback to handle the result of the message processing.
4947
*/
5048
fun process(
5149
jsMessage: JsMessage,
52-
jsMessageCallback: WebViewCompatMessageCallback,
53-
onResponse: (JSONObject) -> Unit,
54-
)
50+
): ProcessResult?
5551

5652
/**
5753
* Method this handler can process.

content-scope-scripts/content-scope-scripts-impl/src/main/java/com/duckduckgo/contentscopescripts/impl/messaging/DebugFlagGlobalHandler.kt

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ import com.duckduckgo.contentscopescripts.api.GlobalContentScopeJsMessageHandler
2020
import com.duckduckgo.contentscopescripts.api.GlobalJsMessageHandler
2121
import com.duckduckgo.di.scopes.AppScope
2222
import com.duckduckgo.js.messaging.api.JsMessage
23-
import com.duckduckgo.js.messaging.api.WebViewCompatMessageCallback
23+
import com.duckduckgo.js.messaging.api.WebViewCompatMessageHandler.ProcessResult
24+
import com.duckduckgo.js.messaging.api.WebViewCompatMessageHandler.ProcessResult.SendToConsumer
2425
import com.squareup.anvil.annotations.ContributesMultibinding
2526
import javax.inject.Inject
2627
import logcat.logcat
27-
import org.json.JSONObject
2828

2929
@ContributesMultibinding(AppScope::class)
3030
class DebugFlagGlobalHandler @Inject constructor() : GlobalContentScopeJsMessageHandlersPlugin {
@@ -33,19 +33,12 @@ class DebugFlagGlobalHandler @Inject constructor() : GlobalContentScopeJsMessage
3333

3434
override fun process(
3535
jsMessage: JsMessage,
36-
jsMessageCallback: WebViewCompatMessageCallback,
37-
onResponse: (JSONObject) -> Unit,
38-
) {
36+
): ProcessResult? {
3937
if (jsMessage.method == method) {
4038
logcat { "DebugFlagGlobalHandler addDebugFlag: ${jsMessage.featureName}" }
41-
jsMessageCallback.process(
42-
featureName = jsMessage.featureName,
43-
method = jsMessage.method,
44-
id = jsMessage.id,
45-
data = jsMessage.params,
46-
onResponse = onResponse,
47-
)
39+
return SendToConsumer
4840
}
41+
return null
4942
}
5043

5144
override val method: String = "addDebugFlag"

content-scope-scripts/content-scope-scripts-impl/src/main/java/com/duckduckgo/contentscopescripts/impl/messaging/WebViewCompatWebCompatMessagingPlugin.kt

Lines changed: 56 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ import com.duckduckgo.di.scopes.ActivityScope
3030
import com.duckduckgo.js.messaging.api.JsCallbackData
3131
import com.duckduckgo.js.messaging.api.JsMessage
3232
import com.duckduckgo.js.messaging.api.WebViewCompatMessageCallback
33+
import com.duckduckgo.js.messaging.api.WebViewCompatMessageHandler.ProcessResult.SendResponse
34+
import com.duckduckgo.js.messaging.api.WebViewCompatMessageHandler.ProcessResult.SendToConsumer
3335
import com.squareup.anvil.annotations.ContributesMultibinding
3436
import com.squareup.moshi.Moshi
3537
import javax.inject.Inject
@@ -71,20 +73,30 @@ class WebViewCompatWebCompatMessagingPlugin @Inject constructor(
7173
.map { it.getGlobalJsMessageHandler() }
7274
.filter { it.method == jsMessage.method }
7375
.forEach { handler ->
74-
handler.process(jsMessage, jsMessageCallback) { }
76+
handler.process(jsMessage)?.let { processResult ->
77+
when (processResult) {
78+
is SendToConsumer -> {
79+
sendToConsumer(jsMessageCallback, jsMessage, replyProxy)
80+
}
81+
is SendResponse -> {
82+
onResponse(jsMessage, replyProxy)
83+
}
84+
}
85+
}
7586
}
7687

7788
// Process with feature handlers
7889
handlers.getPlugins().map { it.getJsMessageHandler() }.firstOrNull {
7990
it.methods.contains(jsMessage.method) && it.featureName == jsMessage.featureName
80-
}?.process(jsMessage, jsMessageCallback) { response: JSONObject ->
81-
val callbackData = JsCallbackData(
82-
id = jsMessage.id ?: "",
83-
params = response,
84-
featureName = jsMessage.featureName,
85-
method = jsMessage.method,
86-
)
87-
onResponse(callbackData, replyProxy)
91+
}?.process(jsMessage)?.let { processResult ->
92+
when (processResult) {
93+
is SendToConsumer -> {
94+
sendToConsumer(jsMessageCallback, jsMessage, replyProxy)
95+
}
96+
is SendResponse -> {
97+
onResponse(jsMessage, replyProxy)
98+
}
99+
}
88100
}
89101
}
90102
}
@@ -93,6 +105,41 @@ class WebViewCompatWebCompatMessagingPlugin @Inject constructor(
93105
}
94106
}
95107

108+
private fun onResponse(
109+
jsMessage: JsMessage,
110+
replyProxy: JavaScriptReplyProxy,
111+
) {
112+
val callbackData = JsCallbackData(
113+
id = jsMessage.id ?: "",
114+
params = jsMessage.params,
115+
featureName = jsMessage.featureName,
116+
method = jsMessage.method,
117+
)
118+
onResponse(callbackData, replyProxy)
119+
}
120+
121+
private fun sendToConsumer(
122+
jsMessageCallback: WebViewCompatMessageCallback,
123+
jsMessage: JsMessage,
124+
replyProxy: JavaScriptReplyProxy,
125+
) {
126+
jsMessageCallback.process(
127+
jsMessage.featureName,
128+
jsMessage.method,
129+
jsMessage.id ?: "",
130+
jsMessage.params,
131+
{ response: JSONObject ->
132+
val callbackData = JsCallbackData(
133+
id = jsMessage.id ?: "",
134+
params = response,
135+
featureName = jsMessage.featureName,
136+
method = jsMessage.method,
137+
)
138+
onResponse(callbackData, replyProxy)
139+
},
140+
)
141+
}
142+
96143
override suspend fun register(
97144
jsMessageCallback: WebViewCompatMessageCallback?,
98145
registerer: suspend (objectName: String, allowedOriginRules: Set<String>, webMessageListener: WebMessageListener) -> Boolean,

content-scope-scripts/content-scope-scripts-impl/src/test/java/com/duckduckgo/contentscopescripts/impl/messaging/WebViewCompatWebCompatMessagingPluginTest.kt

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -59,16 +59,8 @@ class WebViewCompatWebCompatMessagingPluginTest {
5959
return object : WebViewCompatMessageHandler {
6060
override fun process(
6161
jsMessage: JsMessage,
62-
jsMessageCallback: WebViewCompatMessageCallback?,
63-
onResponse: (JSONObject) -> Unit,
64-
) {
65-
jsMessageCallback?.process(
66-
jsMessage.featureName,
67-
jsMessage.method,
68-
jsMessage.id,
69-
jsMessage.params,
70-
onResponse,
71-
)
62+
): WebViewCompatMessageHandler.ProcessResult {
63+
return WebViewCompatMessageHandler.ProcessResult.SendToConsumer
7264
}
7365

7466
override val featureName: String = "webCompat"

js-messaging/js-messaging-api/src/main/java/com/duckduckgo/js/messaging/api/WebViewCompatMessaging.kt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,14 @@ interface WebViewCompatMessageHandler {
4040
* @param onResponse A callback function to send a response back to the JavaScript code.
4141
*/
4242

43-
// TODO: Simplify by removing the onResponse and callback
43+
sealed interface ProcessResult {
44+
data object SendToConsumer : ProcessResult
45+
data class SendResponse(val response: JSONObject) : ProcessResult
46+
}
47+
4448
fun process(
4549
jsMessage: JsMessage,
46-
jsMessageCallback: WebViewCompatMessageCallback?,
47-
onResponse: (JSONObject) -> Unit,
48-
)
50+
): ProcessResult?
4951

5052
/**
5153
* Name of the feature

web-compat/web-compat-impl/src/main/java/com/duckduckgo/webcompat/impl/messaging/webviewcompat/WebViewCompatWebCompatContentScopeJsMessageHandler.kt

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,27 +16,24 @@
1616

1717
package com.duckduckgo.webcompat.impl.messaging.webviewcompat
1818

19-
import com.duckduckgo.contentscopescripts.api.WebCompatContentScopeJsMessageHandlersPlugin
19+
import com.duckduckgo.contentscopescripts.api.WebViewCompatContentScopeJsMessageHandlersPlugin
2020
import com.duckduckgo.di.scopes.AppScope
2121
import com.duckduckgo.js.messaging.api.JsMessage
22-
import com.duckduckgo.js.messaging.api.WebCompatMessageHandler
23-
import com.duckduckgo.js.messaging.api.WebViewCompatMessageCallback
22+
import com.duckduckgo.js.messaging.api.WebViewCompatMessageHandler
23+
import com.duckduckgo.js.messaging.api.WebViewCompatMessageHandler.ProcessResult
2424
import com.squareup.anvil.annotations.ContributesMultibinding
2525
import javax.inject.Inject
26-
import org.json.JSONObject
2726

2827
@ContributesMultibinding(AppScope::class)
29-
class WebViewCompatWebCompatContentScopeJsMessageHandler @Inject constructor() : WebCompatContentScopeJsMessageHandlersPlugin {
28+
class WebViewCompatWebCompatContentScopeJsMessageHandler @Inject constructor() : WebViewCompatContentScopeJsMessageHandlersPlugin {
3029

31-
override fun getJsMessageHandler(): WebCompatMessageHandler = object : WebCompatMessageHandler {
30+
override fun getJsMessageHandler(): WebViewCompatMessageHandler = object : WebViewCompatMessageHandler {
3231

3332
override fun process(
3433
jsMessage: JsMessage,
35-
jsMessageCallback: WebViewCompatMessageCallback?,
36-
onResponse: (JSONObject) -> Unit,
37-
) {
38-
if (jsMessage.id == null) return
39-
jsMessageCallback?.process(featureName, jsMessage.method, jsMessage.id, jsMessage.params, onResponse)
34+
): ProcessResult? {
35+
if (jsMessage.id == null) return null
36+
return ProcessResult.SendToConsumer
4037
}
4138

4239
override val featureName: String = "webCompat"

0 commit comments

Comments
 (0)