Skip to content

Commit 0ae6261

Browse files
committed
Support subscriptions by replying to ping message
1 parent 59f0b6a commit 0ae6261

File tree

6 files changed

+85
-3
lines changed

6 files changed

+85
-3
lines changed

app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1214,7 +1214,8 @@ class BrowserTabFragment :
12141214
private fun onOmnibarCustomTabPrivacyDashboardPressed() {
12151215
val params = PrivacyDashboardPrimaryScreen(tabId)
12161216
val intent = globalActivityStarter.startIntent(requireContext(), params)
1217-
contentScopeScripts.sendSubscriptionEvent(createBreakageReportingEventData())
1217+
adsJsContentScopeScripts.postMessage(createBreakageReportingEventData())
1218+
// contentScopeScripts.sendSubscriptionEvent(createBreakageReportingEventData())
12181219
intent?.let { activityResultPrivacyDashboard.launch(intent) }
12191220
pixel.fire(CustomTabPixelNames.CUSTOM_TABS_PRIVACY_DASHBOARD_OPENED)
12201221
}
@@ -1226,12 +1227,14 @@ class BrowserTabFragment :
12261227
}
12271228

12281229
private fun onBrowserMenuButtonPressed() {
1229-
contentScopeScripts.sendSubscriptionEvent(createBreakageReportingEventData())
1230+
adsJsContentScopeScripts.postMessage(createBreakageReportingEventData())
1231+
// contentScopeScripts.sendSubscriptionEvent(createBreakageReportingEventData())
12301232
viewModel.onBrowserMenuClicked(isCustomTab = isActiveCustomTab())
12311233
}
12321234

12331235
private fun onOmnibarPrivacyShieldButtonPressed() {
1234-
contentScopeScripts.sendSubscriptionEvent(createBreakageReportingEventData())
1236+
adsJsContentScopeScripts.postMessage(createBreakageReportingEventData())
1237+
// contentScopeScripts.sendSubscriptionEvent(createBreakageReportingEventData())
12351238
viewModel.onOmnibarPrivacyShieldButtonPressed()
12361239
launchPrivacyDashboard(toggle = false)
12371240
}

app/src/main/java/com/duckduckgo/app/browser/BrowserTabViewModel.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3669,6 +3669,9 @@ class BrowserTabViewModel @Inject constructor(
36693669
"webShare" -> if (id != null && data != null) {
36703670
adsjsWebShare(featureName, method, id, data, onResponse)
36713671
}
3672+
"breakageReportResult" -> if (data != null) {
3673+
breakageReportResult(data)
3674+
}
36723675
}
36733676
}
36743677

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright (c) 2024 DuckDuckGo
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.duckduckgo.breakagereporting.impl
18+
19+
import com.duckduckgo.contentscopescripts.api.AdsjsContentScopeJsMessageHandlersPlugin
20+
import com.duckduckgo.di.scopes.ActivityScope
21+
import com.duckduckgo.js.messaging.api.AdsjsJsMessageCallback
22+
import com.duckduckgo.js.messaging.api.AdsjsMessageHandler
23+
import com.duckduckgo.js.messaging.api.JsMessage
24+
import com.squareup.anvil.annotations.ContributesMultibinding
25+
import javax.inject.Inject
26+
import org.json.JSONObject
27+
28+
@ContributesMultibinding(ActivityScope::class)
29+
class AdsjsBreakageContentScopeJsMessageHandler @Inject constructor() : AdsjsContentScopeJsMessageHandlersPlugin {
30+
31+
override fun getJsMessageHandler(): AdsjsMessageHandler = object : AdsjsMessageHandler {
32+
33+
override fun process(
34+
jsMessage: JsMessage,
35+
jsMessageCallback: AdsjsJsMessageCallback?,
36+
onResponse: (JSONObject) -> Unit,
37+
) {
38+
jsMessageCallback?.process(featureName, jsMessage.method, jsMessage.id, jsMessage.params, onResponse)
39+
}
40+
41+
override val featureName: String = "breakageReporting"
42+
override val methods: List<String> = listOf("breakageReportResult")
43+
}
44+
}

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package com.duckduckgo.contentscopescripts.impl.messaging
1818

19+
import android.annotation.SuppressLint
1920
import android.webkit.WebView
2021
import androidx.annotation.VisibleForTesting
2122
import androidx.webkit.JavaScriptReplyProxy
@@ -31,6 +32,8 @@ import com.duckduckgo.js.messaging.api.AdsjsJsMessageCallback
3132
import com.duckduckgo.js.messaging.api.AdsjsMessaging
3233
import com.duckduckgo.js.messaging.api.JsCallbackData
3334
import com.duckduckgo.js.messaging.api.JsMessage
35+
import com.duckduckgo.js.messaging.api.SubscriptionEvent
36+
import com.duckduckgo.js.messaging.api.SubscriptionEventData
3437
import com.squareup.anvil.annotations.ContributesBinding
3538
import com.squareup.moshi.Moshi
3639
import javax.inject.Inject
@@ -62,6 +65,8 @@ class AdsjsContentScopeMessaging @Inject constructor(
6265
override val context: String = "contentScopeScripts"
6366
override val allowedDomains: Set<String> = setOf("*")
6467

68+
private var globalReplyProxy: JavaScriptReplyProxy? = null
69+
6570
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
6671
internal fun process(
6772
message: String,
@@ -75,6 +80,11 @@ class AdsjsContentScopeMessaging @Inject constructor(
7580
jsMessage?.let {
7681
if (context == jsMessage.context) {
7782
// Process global handlers first (always processed regardless of feature handlers)
83+
84+
if (jsMessage.featureName == "messaging" || jsMessage.method == "initialPing") {
85+
globalReplyProxy = replyProxy
86+
}
87+
7888
globalHandlers.getPlugins()
7989
.map { it.getGlobalJsMessageHandler() }
8090
.filter { it.method == jsMessage.method }
@@ -158,4 +168,20 @@ class AdsjsContentScopeMessaging @Inject constructor(
158168
}
159169
}
160170
}
171+
172+
@SuppressLint("RequiresFeature")
173+
override fun postMessage(subscriptionEventData: SubscriptionEventData) {
174+
runCatching {
175+
val subscriptionEvent = SubscriptionEvent(
176+
context = context,
177+
featureName = subscriptionEventData.featureName,
178+
subscriptionName = subscriptionEventData.subscriptionName,
179+
params = subscriptionEventData.params,
180+
).let {
181+
moshi.adapter(SubscriptionEvent::class.java).toJson(it)
182+
}
183+
184+
globalReplyProxy?.postMessage(subscriptionEvent)
185+
}
186+
}
161187
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ interface AdsjsMessaging {
3030
)
3131
suspend fun unregister(webView: WebView)
3232

33+
fun postMessage(subscriptionEventData: SubscriptionEventData)
34+
3335
/**
3436
* Context name
3537
*/

js-messaging/js-messaging-impl/src/main/java/com/duckduckgo/js/messaging/impl/RealJsMessageHelper.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import dagger.SingleInstanceIn
3333
import javax.inject.Inject
3434
import kotlinx.coroutines.CoroutineScope
3535
import kotlinx.coroutines.launch
36+
import logcat.logcat
3637

3738
@SingleInstanceIn(AppScope::class)
3839
@ContributesBinding(AppScope::class)
@@ -47,6 +48,9 @@ class RealJsMessageHelper @Inject constructor(
4748
val jsonAdapter: JsonAdapter<SubscriptionEvent> = moshi.adapter(SubscriptionEvent::class.java)
4849
val message = jsonAdapter.toJson(subscriptionEvent).toString()
4950
val response = buildJsResponse(message, callbackName, secret)
51+
52+
logcat("Cris") { "$response" }
53+
5054
sendResponse(response, webView)
5155
}
5256

0 commit comments

Comments
 (0)