Skip to content

Commit

Permalink
Add pixels
Browse files Browse the repository at this point in the history
  • Loading branch information
CrisBarreiro committed Aug 21, 2024
1 parent 3e646bc commit d65ba65
Show file tree
Hide file tree
Showing 9 changed files with 195 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ import com.duckduckgo.app.onboarding.store.UserStageStore
import com.duckduckgo.app.onboarding.ui.page.extendedonboarding.ExtendedOnboardingFeatureToggles
import com.duckduckgo.app.pixels.AppPixelName
import com.duckduckgo.app.pixels.AppPixelName.AUTOCOMPLETE_BANNER_SHOWN
import com.duckduckgo.app.pixels.AppPixelName.DUCK_PLAYER_SETTING_ALWAYS_DUCK_PLAYER
import com.duckduckgo.app.pixels.AppPixelName.DUCK_PLAYER_SETTING_ALWAYS_OVERLAY_YOUTUBE
import com.duckduckgo.app.pixels.AppPixelName.DUCK_PLAYER_SETTING_NEVER_OVERLAY_YOUTUBE
import com.duckduckgo.app.pixels.AppPixelName.ONBOARDING_SEARCH_CUSTOM
import com.duckduckgo.app.pixels.AppPixelName.ONBOARDING_VISIT_SITE_CUSTOM
import com.duckduckgo.app.pixels.remoteconfig.AndroidBrowserConfigFeature
Expand Down Expand Up @@ -645,7 +648,7 @@ class BrowserTabViewModelTest {
newTabPixels = { mockNewTabPixels },
httpErrorPixels = { mockHttpErrorPixels },
duckPlayer = mockDuckPlayer,
duckPlayerJSHelper = DuckPlayerJSHelper(mockDuckPlayer, mockAppBuildConfig),
duckPlayerJSHelper = DuckPlayerJSHelper(mockDuckPlayer, mockAppBuildConfig, mockPixel),
)

testee.loadData("abc", null, false, false)
Expand Down Expand Up @@ -4912,17 +4915,33 @@ class BrowserTabViewModelTest {
}

@Test
fun whenProcessJsCallbackMessageSetUserPreferencesFromDuckPlayerOverlayThenSendCommand() = runTest {
fun whenProcessJsCallbackMessageSetUserPreferencesDisabledFromDuckPlayerOverlayThenSendCommand() = runTest {
whenever(mockEnabledToggle.isEnabled()).thenReturn(true)
whenever(mockDuckPlayer.getUserPreferences()).thenReturn(UserPreferences(overlayInteracted = true, privatePlayerMode = AlwaysAsk))
testee.processJsCallbackMessage(
DUCK_PLAYER_FEATURE_NAME,
"setUserValues",
"id",
JSONObject("""{ overlayInteracted: "true", privatePlayerMode: {alwaysAsk: {} }}"""),
JSONObject("""{ overlayInteracted: "true", privatePlayerMode: {disabled: {} }}"""),
)
assertCommandIssued<Command.SendResponseToJs>()
verify(mockDuckPlayer).setUserPreferences(any(), any())
verify(mockPixel).fire(DUCK_PLAYER_SETTING_NEVER_OVERLAY_YOUTUBE)
}

@Test
fun whenProcessJsCallbackMessageSetUserPreferencesEnabledFromDuckPlayerOverlayThenSendCommand() = runTest {
whenever(mockEnabledToggle.isEnabled()).thenReturn(true)
whenever(mockDuckPlayer.getUserPreferences()).thenReturn(UserPreferences(overlayInteracted = true, privatePlayerMode = AlwaysAsk))
testee.processJsCallbackMessage(
DUCK_PLAYER_FEATURE_NAME,
"setUserValues",
"id",
JSONObject("""{ overlayInteracted: "true", privatePlayerMode: {enabled: {} }}"""),
)
assertCommandIssued<Command.SendResponseToJs>()
verify(mockDuckPlayer).setUserPreferences(any(), any())
verify(mockPixel).fire(DUCK_PLAYER_SETTING_ALWAYS_OVERLAY_YOUTUBE)
}

@Test
Expand All @@ -4933,10 +4952,11 @@ class BrowserTabViewModelTest {
DUCK_PLAYER_PAGE_FEATURE_NAME,
"setUserValues",
"id",
JSONObject("""{ overlayInteracted: "true", privatePlayerMode: {alwaysAsk: {} }}"""),
JSONObject("""{ overlayInteracted: "true", privatePlayerMode: {enabled: {} }}"""),
)
assertCommandIssued<Command.SendResponseToDuckPlayer>()
verify(mockDuckPlayer).setUserPreferences(true, "alwaysAsk")
verify(mockDuckPlayer).setUserPreferences(true, "enabled")
verify(mockPixel).fire(DUCK_PLAYER_SETTING_ALWAYS_DUCK_PLAYER)
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,17 @@

package com.duckduckgo.app.browser.duckplayer

import androidx.core.net.toUri
import com.duckduckgo.app.browser.commands.Command
import com.duckduckgo.app.browser.commands.Command.OpenDuckPlayerInfo
import com.duckduckgo.app.browser.commands.Command.OpenDuckPlayerSettings
import com.duckduckgo.app.browser.commands.Command.SendResponseToDuckPlayer
import com.duckduckgo.app.browser.commands.Command.SendResponseToJs
import com.duckduckgo.app.browser.commands.NavigationCommand.Navigate
import com.duckduckgo.app.pixels.AppPixelName.DUCK_PLAYER_SETTING_ALWAYS_DUCK_PLAYER
import com.duckduckgo.app.pixels.AppPixelName.DUCK_PLAYER_SETTING_ALWAYS_OVERLAY_YOUTUBE
import com.duckduckgo.app.pixels.AppPixelName.DUCK_PLAYER_SETTING_NEVER_OVERLAY_YOUTUBE
import com.duckduckgo.app.statistics.pixels.Pixel
import com.duckduckgo.appbuildconfig.api.AppBuildConfig
import com.duckduckgo.duckplayer.api.DuckPlayer
import com.duckduckgo.js.messaging.api.JsCallbackData
Expand All @@ -37,6 +42,7 @@ private const val PRIVATE_PLAYER_MODE = "privatePlayerMode"
class DuckPlayerJSHelper @Inject constructor(
private val duckPlayer: DuckPlayer,
private val appBuildConfig: AppBuildConfig,
private val pixel: Pixel,
) {
private suspend fun getUserPreferences(featureName: String, method: String, id: String): JsCallbackData {
val userValues = duckPlayer.getUserPreferences()
Expand Down Expand Up @@ -126,10 +132,20 @@ class DuckPlayerJSHelper @Inject constructor(
setUserPreferences(data)
return when (featureName) {
DUCK_PLAYER_FEATURE_NAME -> {
SendResponseToJs(getUserPreferences(featureName, method, id))
SendResponseToJs(getUserPreferences(featureName, method, id)).also {
if (data.getJSONObject(PRIVATE_PLAYER_MODE).keys().next() == "enabled") {
pixel.fire(DUCK_PLAYER_SETTING_ALWAYS_OVERLAY_YOUTUBE)
} else if (data.getJSONObject(PRIVATE_PLAYER_MODE).keys().next() == "disabled") {
pixel.fire(DUCK_PLAYER_SETTING_NEVER_OVERLAY_YOUTUBE)
}
}
}
DUCK_PLAYER_PAGE_FEATURE_NAME -> {
SendResponseToDuckPlayer(getUserPreferences(featureName, method, id))
SendResponseToDuckPlayer(getUserPreferences(featureName, method, id)).also {
if (data.getJSONObject(PRIVATE_PLAYER_MODE).keys().next() == "enabled") {
pixel.fire(DUCK_PLAYER_SETTING_ALWAYS_DUCK_PLAYER)
}
}
} else -> {
null
}
Expand All @@ -142,7 +158,7 @@ class DuckPlayerJSHelper @Inject constructor(
}
"openDuckPlayer" -> {
return data?.getString("href")?.let {
Navigate(it, mapOf())
Navigate(it.toUri().buildUpon().appendQueryParameter("origin", "overlay").build().toString(), mapOf())
}
}
"initialSetup" -> {
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/java/com/duckduckgo/app/pixels/AppPixelName.kt
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,10 @@ enum class AppPixelName(override val pixelName: String) : Pixel.PixelName {
TAB_MANAGER_LIST_VIEW_BUTTON_CLICKED("m_tab_manager_list_view_button_clicked"),
TAB_MANAGER_VIEW_MODE_TOGGLED_DAILY("m_tab_manager_view_mode_toggled_daily"),

DUCK_PLAYER_SETTING_ALWAYS_OVERLAY_YOUTUBE("duck-player_setting_always_overlay_youtube"),
DUCK_PLAYER_SETTING_NEVER_OVERLAY_YOUTUBE("duck-player_setting_never_overlay_youtube"),
DUCK_PLAYER_SETTING_ALWAYS_DUCK_PLAYER("duck-player_setting_always_duck-player"),

ADD_BOOKMARK_CONFIRM_EDITED("m_add_bookmark_confirm_edit"),

REFERRAL_INSTALL_UTM_CAMPAIGN("m_android_install"),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
package com.duckduckgo.duckplayer.impl

import app.cash.turbine.test
import com.duckduckgo.app.statistics.pixels.Pixel
import com.duckduckgo.common.test.CoroutineTestRule
import com.duckduckgo.duckplayer.api.DuckPlayer
import com.duckduckgo.duckplayer.api.DuckPlayer.UserPreferences
import com.duckduckgo.duckplayer.api.PrivatePlayerMode.AlwaysAsk
import com.duckduckgo.duckplayer.api.PrivatePlayerMode.Disabled
import com.duckduckgo.duckplayer.api.PrivatePlayerMode.Enabled
import com.duckduckgo.duckplayer.impl.DuckPlayerPixelName.DUCK_PLAYER_SETTINGS_ALWAYS_SETTINGS
import com.duckduckgo.duckplayer.impl.DuckPlayerPixelName.DUCK_PLAYER_SETTINGS_BACK_TO_DEFAULT
import com.duckduckgo.duckplayer.impl.DuckPlayerPixelName.DUCK_PLAYER_SETTINGS_NEVER_SETTINGS
import com.duckduckgo.duckplayer.impl.DuckPlayerSettingsViewModel.Command.OpenPlayerModeSelector
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.flowOf
Expand All @@ -27,13 +32,14 @@ class DuckPlayerSettingsViewModelTest {

private val duckPlayer: DuckPlayer = mock()
private val duckPlayerFeatureRepository: DuckPlayerFeatureRepository = mock()
private val pixel: Pixel = mock()
private lateinit var viewModel: DuckPlayerSettingsViewModel

@Before
fun setUp() {
runTest {
whenever(duckPlayer.getUserPreferences()).thenReturn(UserPreferences(overlayInteracted = true, privatePlayerMode = AlwaysAsk))
viewModel = DuckPlayerSettingsViewModel(duckPlayer, duckPlayerFeatureRepository)
viewModel = DuckPlayerSettingsViewModel(duckPlayer, duckPlayerFeatureRepository, pixel)
}
}

Expand All @@ -51,12 +57,29 @@ class DuckPlayerSettingsViewModelTest {
viewModel.onPlayerModeSelected(Disabled)

verify(duckPlayer).setUserPreferences(overlayInteracted = false, privatePlayerMode = Disabled.value)
verify(pixel).fire(DUCK_PLAYER_SETTINGS_NEVER_SETTINGS)
}

@Test
fun whenPrivatePlayerModeIsSelectedToAlwaysAskThenUpdateUserPreferences() = runTest {
viewModel.onPlayerModeSelected(AlwaysAsk)

verify(duckPlayer).setUserPreferences(overlayInteracted = false, privatePlayerMode = AlwaysAsk.value)
verify(pixel).fire(DUCK_PLAYER_SETTINGS_BACK_TO_DEFAULT)
}

@Test
fun whenPrivatePlayerModeIsSelectedToAlwaysThenUpdateUserPreferences() = runTest {
viewModel.onPlayerModeSelected(Enabled)

verify(duckPlayer).setUserPreferences(overlayInteracted = false, privatePlayerMode = Enabled.value)
verify(pixel).fire(DUCK_PLAYER_SETTINGS_ALWAYS_SETTINGS)
}

@Test
fun whenViewModelIsCreatedAndPrivatePlayerModeIsDisabledThenEmitDisabled() = runTest {
whenever(duckPlayer.observeUserPreferences()).thenReturn(flowOf(UserPreferences(overlayInteracted = true, privatePlayerMode = Disabled)))
viewModel = DuckPlayerSettingsViewModel(duckPlayer, duckPlayerFeatureRepository)
viewModel = DuckPlayerSettingsViewModel(duckPlayer, duckPlayerFeatureRepository, pixel)

viewModel.viewState.test {
assertEquals(Disabled, awaitItem().privatePlayerMode)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 DuckDuckGo
* Copyright (c) 2024 DuckDuckGo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -19,5 +19,15 @@ package com.duckduckgo.duckplayer.impl
import com.duckduckgo.app.statistics.pixels.Pixel

enum class DuckPlayerPixelName(override val pixelName: String) : Pixel.PixelName {
SETTINGS_DUCK_PLAYER_PRESSED("ms_duck_player_setting_pressed"),
DUCK_PLAYER_OVERLAY_YOUTUBE_IMPRESSIONS("duck-player_overlay_youtube_impressions"),
DUCK_PLAYER_VIEW_FROM_YOUTUBE_MAIN_OVERLAY("duck-player_view-from_youtube_main-overlay"),
DUCK_PLAYER_OVERLAY_YOUTUBE_WATCH_HERE("duck-player_overlay_youtube_watch_here"),
DUCK_PLAYER_WATCH_ON_YOUTUBE("duck-player_watch_on_youtube"),
DUCK_PLAYER_DAILY_UNIQUE_VIEW("duck-player_daily-unique-view"),
DUCK_PLAYER_VIEW_FROM_YOUTUBE_AUTOMATIC("duck-player_view-from_youtube_automatic"),
DUCK_PLAYER_VIEW_FROM_OTHER("duck-player_view-from_other"),
DUCK_PLAYER_SETTINGS_ALWAYS_SETTINGS("duck-player_setting_always_settings"),
DUCK_PLAYER_SETTINGS_BACK_TO_DEFAULT("duck-player_setting_back-to-default"),
DUCK_PLAYER_SETTINGS_NEVER_SETTINGS("duck-player_setting_never_settings"),
DUCK_PLAYER_SETTINGS_PRESSED("duck_player_setting_pressed"),
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import com.duckduckgo.app.statistics.pixels.Pixel
import com.duckduckgo.common.ui.view.listitem.OneLineListItem
import com.duckduckgo.di.scopes.ActivityScope
import com.duckduckgo.duckplayer.api.DuckPlayerSettingsNoParams
import com.duckduckgo.duckplayer.impl.DuckPlayerPixelName.SETTINGS_DUCK_PLAYER_PRESSED
import com.duckduckgo.duckplayer.impl.DuckPlayerPixelName.DUCK_PLAYER_SETTINGS_PRESSED
import com.duckduckgo.navigation.api.GlobalActivityStarter
import com.duckduckgo.settings.api.DuckPlayerSettingsPlugin
import com.squareup.anvil.annotations.ContributesMultibinding
Expand All @@ -39,7 +39,7 @@ class DuckPlayerSettingsTitle @Inject constructor(
return OneLineListItem(context).apply {
setPrimaryText(context.getString(R.string.duck_player_setting_title))
setOnClickListener {
pixel.fire(SETTINGS_DUCK_PLAYER_PRESSED)
pixel.fire(DUCK_PLAYER_SETTINGS_PRESSED)
globalActivityStarter.start(this.context, DuckPlayerSettingsNoParams, null)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,16 @@ package com.duckduckgo.duckplayer.impl
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.duckduckgo.anvil.annotations.ContributesViewModel
import com.duckduckgo.app.statistics.pixels.Pixel
import com.duckduckgo.di.scopes.ActivityScope
import com.duckduckgo.duckplayer.api.DuckPlayer
import com.duckduckgo.duckplayer.api.DuckPlayer.DuckPlayerState.DISABLED_WIH_HELP_LINK
import com.duckduckgo.duckplayer.api.PrivatePlayerMode
import com.duckduckgo.duckplayer.api.PrivatePlayerMode.AlwaysAsk
import com.duckduckgo.duckplayer.api.PrivatePlayerMode.Disabled
import com.duckduckgo.duckplayer.impl.DuckPlayerPixelName.DUCK_PLAYER_SETTINGS_ALWAYS_SETTINGS
import com.duckduckgo.duckplayer.impl.DuckPlayerPixelName.DUCK_PLAYER_SETTINGS_BACK_TO_DEFAULT
import com.duckduckgo.duckplayer.impl.DuckPlayerPixelName.DUCK_PLAYER_SETTINGS_NEVER_SETTINGS
import com.duckduckgo.duckplayer.impl.DuckPlayerSettingsViewModel.Command.OpenLearnMore
import com.duckduckgo.duckplayer.impl.DuckPlayerSettingsViewModel.Command.OpenPlayerModeSelector
import com.duckduckgo.duckplayer.impl.DuckPlayerSettingsViewModel.ViewState.DisabledWithHelpLink
Expand All @@ -43,6 +48,7 @@ import kotlinx.coroutines.runBlocking
class DuckPlayerSettingsViewModel @Inject constructor(
private val duckPlayer: DuckPlayer,
private val duckPlayerFeatureRepository: DuckPlayerFeatureRepository,
private val pixel: Pixel,
) : ViewModel() {

private val commandChannel = Channel<Command>(capacity = 1, onBufferOverflow = DROP_OLDEST)
Expand Down Expand Up @@ -81,7 +87,14 @@ class DuckPlayerSettingsViewModel @Inject constructor(

fun onPlayerModeSelected(selectedPlayerMode: PrivatePlayerMode) {
viewModelScope.launch {
duckPlayer.setUserPreferences(overlayInteracted = false, privatePlayerMode = selectedPlayerMode.value)
duckPlayer.setUserPreferences(overlayInteracted = false, privatePlayerMode = selectedPlayerMode.value).also {
val pixelName = when (selectedPlayerMode) {
is PrivatePlayerMode.Enabled -> { DUCK_PLAYER_SETTINGS_ALWAYS_SETTINGS }
is AlwaysAsk -> { DUCK_PLAYER_SETTINGS_BACK_TO_DEFAULT }
is Disabled -> { DUCK_PLAYER_SETTINGS_NEVER_SETTINGS }
}
pixel.fire(pixelName)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import android.webkit.WebView
import androidx.core.net.toUri
import androidx.fragment.app.FragmentManager
import com.duckduckgo.app.statistics.pixels.Pixel
import com.duckduckgo.app.statistics.pixels.Pixel.PixelType.DAILY
import com.duckduckgo.common.utils.DispatcherProvider
import com.duckduckgo.common.utils.UrlScheme.Companion.duck
import com.duckduckgo.common.utils.UrlScheme.Companion.https
Expand All @@ -38,6 +39,13 @@ import com.duckduckgo.duckplayer.api.DuckPlayer.UserPreferences
import com.duckduckgo.duckplayer.api.PrivatePlayerMode.AlwaysAsk
import com.duckduckgo.duckplayer.api.PrivatePlayerMode.Disabled
import com.duckduckgo.duckplayer.api.PrivatePlayerMode.Enabled
import com.duckduckgo.duckplayer.impl.DuckPlayerPixelName.DUCK_PLAYER_DAILY_UNIQUE_VIEW
import com.duckduckgo.duckplayer.impl.DuckPlayerPixelName.DUCK_PLAYER_OVERLAY_YOUTUBE_IMPRESSIONS
import com.duckduckgo.duckplayer.impl.DuckPlayerPixelName.DUCK_PLAYER_OVERLAY_YOUTUBE_WATCH_HERE
import com.duckduckgo.duckplayer.impl.DuckPlayerPixelName.DUCK_PLAYER_VIEW_FROM_OTHER
import com.duckduckgo.duckplayer.impl.DuckPlayerPixelName.DUCK_PLAYER_VIEW_FROM_YOUTUBE_AUTOMATIC
import com.duckduckgo.duckplayer.impl.DuckPlayerPixelName.DUCK_PLAYER_VIEW_FROM_YOUTUBE_MAIN_OVERLAY
import com.duckduckgo.duckplayer.impl.DuckPlayerPixelName.DUCK_PLAYER_WATCH_ON_YOUTUBE
import com.duckduckgo.duckplayer.impl.ui.DuckPlayerPrimeBottomSheet
import com.duckduckgo.duckplayer.impl.ui.DuckPlayerPrimeDialogFragment
import com.squareup.anvil.annotations.ContributesBinding
Expand Down Expand Up @@ -128,8 +136,12 @@ class RealDuckPlayer @Inject constructor(
pixelName: String,
pixelData: Map<String, String>,
) {
val androidPixelName = "m_${pixelName.replace('.', '_')}"
pixel.fire(androidPixelName, pixelData)
when (pixelName) {
"overlay" -> pixel.fire(DUCK_PLAYER_OVERLAY_YOUTUBE_IMPRESSIONS, parameters = pixelData)
"play.use" -> pixel.fire(DUCK_PLAYER_VIEW_FROM_YOUTUBE_MAIN_OVERLAY, parameters = pixelData)
"play.do_not_use" -> pixel.fire(DUCK_PLAYER_OVERLAY_YOUTUBE_WATCH_HERE, parameters = pixelData)
else -> {}
}
}

private suspend fun createYoutubeNoCookieFromDuckPlayer(uri: Uri): String? {
Expand Down Expand Up @@ -157,6 +169,7 @@ class RealDuckPlayer @Inject constructor(
if (getUserPreferences().privatePlayerMode == AlwaysAsk) {
shouldHideOverlay = true
}
pixel.fire(DUCK_PLAYER_WATCH_ON_YOUTUBE)
}
private fun isDuckPlayerUri(uri: Uri): Boolean {
if (uri.normalizeScheme()?.scheme != duck) return false
Expand Down Expand Up @@ -207,7 +220,7 @@ class RealDuckPlayer @Inject constructor(

private suspend fun createDuckPlayerUriFromYoutube(uri: Uri): String {
val videoIdQueryParam = duckPlayerFeatureRepository.getVideoIDQueryParam()
return "$DUCK_PLAYER_URL_BASE${uri.getQueryParameter(videoIdQueryParam)}"
return "$DUCK_PLAYER_URL_BASE${uri.getQueryParameter(videoIdQueryParam)}?origin=auto"
}

override suspend fun intercept(
Expand Down Expand Up @@ -242,7 +255,9 @@ class RealDuckPlayer @Inject constructor(
}
} else {
val inputStream: InputStream = webView.context.assets.open(DUCK_PLAYER_ASSETS_INDEX_PATH)
return WebResourceResponse("text/html", "UTF-8", inputStream)
return WebResourceResponse("text/html", "UTF-8", inputStream).also {
pixel.fire(DUCK_PLAYER_DAILY_UNIQUE_VIEW, type = DAILY)
}
}
}

Expand Down Expand Up @@ -271,6 +286,7 @@ class RealDuckPlayer @Inject constructor(
withContext(dispatchers.main()) {
webView.loadUrl(createDuckPlayerUriFromYoutube(url))
}
pixel.fire(DUCK_PLAYER_VIEW_FROM_YOUTUBE_AUTOMATIC)
return WebResourceResponse(null, null, null)
}
return null
Expand All @@ -292,6 +308,9 @@ class RealDuckPlayer @Inject constructor(
withContext(dispatchers.main()) {
webView.loadUrl(youtubeUrl)
}
if (url.getQueryParameter("origin") != "overlay" && url.getQueryParameter("origin") != "auto") {
pixel.fire(DUCK_PLAYER_VIEW_FROM_OTHER)
}
}
}
return WebResourceResponse(null, null, null)
Expand Down
Loading

0 comments on commit d65ba65

Please sign in to comment.