Bug 1797593 - Add re-engagement dialog for cookie banners.
This commit is contained in:
parent
614ba71842
commit
804d286650
|
@ -6932,6 +6932,72 @@ cookie_banners:
|
|||
metadata:
|
||||
tags:
|
||||
- Privacy&Security
|
||||
visited_re_engagement_dialog:
|
||||
type: event
|
||||
description: An user visited the cookie banner re-engagement dialog
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1797593
|
||||
data_reviews:
|
||||
- https://github.com/mozilla-mobile/fenix/pull/28405#issuecomment-1372489596
|
||||
data_sensitivity:
|
||||
- interaction
|
||||
notification_emails:
|
||||
- android-probes@mozilla.com
|
||||
expires: 118
|
||||
metadata:
|
||||
tags:
|
||||
- Privacy&Security
|
||||
opt_out_re_engagement_dialog:
|
||||
type: event
|
||||
description: |
|
||||
An user opt out the cookie banner re-engagement
|
||||
dialog by clicking the X button
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1797593
|
||||
data_reviews:
|
||||
- https://github.com/mozilla-mobile/fenix/pull/28405#issuecomment-1372489596
|
||||
data_sensitivity:
|
||||
- interaction
|
||||
notification_emails:
|
||||
- android-probes@mozilla.com
|
||||
expires: 118
|
||||
metadata:
|
||||
tags:
|
||||
- Privacy&Security
|
||||
not_now_re_engagement_dialog:
|
||||
type: event
|
||||
description: |
|
||||
An user clicked the not now button on
|
||||
the cookie banner re-engagement dialog
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1797593
|
||||
data_reviews:
|
||||
- https://github.com/mozilla-mobile/fenix/pull/28405#issuecomment-1372489596
|
||||
data_sensitivity:
|
||||
- interaction
|
||||
notification_emails:
|
||||
- android-probes@mozilla.com
|
||||
expires: 118
|
||||
metadata:
|
||||
tags:
|
||||
- Privacy&Security
|
||||
allow_re_engagement_dialog:
|
||||
type: event
|
||||
description: |
|
||||
An user clicked the dismiss banner button
|
||||
on the cookie banner re-engagement dialog
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1797593
|
||||
data_reviews:
|
||||
- https://github.com/mozilla-mobile/fenix/pull/28405#issuecomment-1372489596
|
||||
data_sensitivity:
|
||||
- interaction
|
||||
notification_emails:
|
||||
- android-probes@mozilla.com
|
||||
expires: 118
|
||||
metadata:
|
||||
tags:
|
||||
- Privacy&Security
|
||||
site_permissions:
|
||||
prompt_shown:
|
||||
type: event
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.junit.Rule
|
|||
import org.junit.Test
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.customannotations.SmokeTest
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
|
||||
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
|
||||
import org.mozilla.fenix.helpers.TestAssetHelper
|
||||
|
@ -53,6 +54,7 @@ class SettingsPrivacyTest {
|
|||
@Before
|
||||
fun setUp() {
|
||||
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
|
||||
appContext.settings().userOptOutOfReEngageCookieBannerDialog = true
|
||||
mockWebServer = MockWebServer().apply {
|
||||
dispatcher = AndroidAssetDispatcher()
|
||||
start()
|
||||
|
|
|
@ -13,10 +13,12 @@ import org.junit.Ignore
|
|||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.customannotations.SmokeTest
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
|
||||
import org.mozilla.fenix.helpers.Constants.defaultTopSitesList
|
||||
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
|
||||
import org.mozilla.fenix.helpers.TestAssetHelper
|
||||
import org.mozilla.fenix.helpers.TestHelper
|
||||
import org.mozilla.fenix.helpers.TestHelper.exitMenu
|
||||
import org.mozilla.fenix.helpers.TestHelper.getSponsoredShortcutTitle
|
||||
import org.mozilla.fenix.ui.robots.homeScreen
|
||||
|
@ -37,6 +39,7 @@ class SponsoredShortcutsTest {
|
|||
|
||||
@Before
|
||||
fun setUp() {
|
||||
TestHelper.appContext.settings().userOptOutOfReEngageCookieBannerDialog = true
|
||||
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
|
||||
mockWebServer = MockWebServer().apply {
|
||||
dispatcher = AndroidAssetDispatcher()
|
||||
|
|
|
@ -15,11 +15,14 @@ import androidx.lifecycle.lifecycleScope
|
|||
import androidx.navigation.fragment.findNavController
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.mapNotNull
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import mozilla.components.browser.state.selector.findCustomTabOrSelectedTab
|
||||
import mozilla.components.browser.state.selector.findTab
|
||||
import mozilla.components.browser.state.state.SessionState
|
||||
import mozilla.components.browser.state.state.TabSessionState
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.browser.thumbnails.BrowserThumbnails
|
||||
import mozilla.components.browser.toolbar.BrowserToolbar
|
||||
import mozilla.components.concept.engine.permission.SitePermissions
|
||||
|
@ -28,9 +31,11 @@ import mozilla.components.feature.contextmenu.ContextMenuCandidate
|
|||
import mozilla.components.feature.readerview.ReaderViewFeature
|
||||
import mozilla.components.feature.tab.collections.TabCollection
|
||||
import mozilla.components.feature.tabs.WindowFeature
|
||||
import mozilla.components.lib.state.ext.consumeFlow
|
||||
import mozilla.components.service.glean.private.NoExtras
|
||||
import mozilla.components.support.base.feature.UserInteractionHandler
|
||||
import mozilla.components.support.base.feature.ViewBoundFeatureWrapper
|
||||
import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifAnyChanged
|
||||
import org.mozilla.fenix.GleanMetrics.ReaderMode
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.FenixSnackbar
|
||||
|
@ -43,6 +48,7 @@ import org.mozilla.fenix.ext.requireComponents
|
|||
import org.mozilla.fenix.ext.runIfFragmentIsAttached
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.nimbus.FxNimbus
|
||||
import org.mozilla.fenix.settings.quicksettings.protections.cookiebanners.dialog.CookieBannerReEngagementDialogUtils
|
||||
import org.mozilla.fenix.shortcut.PwaOnboardingObserver
|
||||
import org.mozilla.fenix.theme.ThemeManager
|
||||
|
||||
|
@ -173,6 +179,9 @@ class BrowserFragment : BaseBrowserFragment(), UserInteractionHandler {
|
|||
view = view,
|
||||
)
|
||||
}
|
||||
if (!context.settings().shouldUseCookieBanner && !context.settings().userOptOutOfReEngageCookieBannerDialog) {
|
||||
observeCookieBannerHandlingState(context.components.core.store)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onUpdateToolbarForConfigurationChange(toolbar: BrowserToolbarView) {
|
||||
|
@ -370,12 +379,17 @@ class BrowserFragment : BaseBrowserFragment(), UserInteractionHandler {
|
|||
useCase.containsException(tab.id) { hasTrackingProtectionException ->
|
||||
lifecycleScope.launch(Dispatchers.Main) {
|
||||
val cookieBannersStorage = requireComponents.core.cookieBannersStorage
|
||||
val hasCookieBannerException = withContext(Dispatchers.IO) {
|
||||
cookieBannersStorage.hasException(
|
||||
tab.content.url,
|
||||
tab.content.private,
|
||||
)
|
||||
}
|
||||
val hasCookieBannerException =
|
||||
if (requireContext().settings().shouldUseCookieBanner) {
|
||||
withContext(Dispatchers.IO) {
|
||||
cookieBannersStorage.hasException(
|
||||
tab.content.url,
|
||||
tab.content.private,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
runIfFragmentIsAttached {
|
||||
val isTrackingProtectionEnabled =
|
||||
tab.trackingProtection.enabled && !hasTrackingProtectionException
|
||||
|
@ -476,4 +490,22 @@ class BrowserFragment : BaseBrowserFragment(), UserInteractionHandler {
|
|||
internal fun updateLastBrowseActivity() {
|
||||
requireContext().settings().lastBrowseActivity = System.currentTimeMillis()
|
||||
}
|
||||
|
||||
private fun observeCookieBannerHandlingState(store: BrowserStore) {
|
||||
consumeFlow(store) { flow ->
|
||||
flow.mapNotNull { state ->
|
||||
state.findCustomTabOrSelectedTab(customTabSessionId)
|
||||
}.ifAnyChanged { tab ->
|
||||
arrayOf(
|
||||
tab.cookieBanner,
|
||||
)
|
||||
}.collect {
|
||||
CookieBannerReEngagementDialogUtils.tryToShowReEngagementDialog(
|
||||
settings = requireContext().settings(),
|
||||
status = it.cookieBanner,
|
||||
navController = findNavController(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,12 +11,14 @@ import androidx.compose.material.Text
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.style.TextDecoration
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.findNavController
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.mapNotNull
|
||||
import kotlinx.coroutines.flow.transformWhile
|
||||
import mozilla.components.browser.state.selector.findCustomTabOrSelectedTab
|
||||
import mozilla.components.browser.state.selector.selectedTab
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.browser.toolbar.BrowserToolbar
|
||||
import mozilla.components.lib.state.ext.flowScoped
|
||||
|
@ -29,6 +31,7 @@ import org.mozilla.fenix.compose.cfr.CFRPopupProperties
|
|||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.settings.SupportUtils
|
||||
import org.mozilla.fenix.settings.SupportUtils.SumoTopic.TOTAL_COOKIE_PROTECTION
|
||||
import org.mozilla.fenix.settings.quicksettings.protections.cookiebanners.dialog.CookieBannerReEngagementDialogUtils
|
||||
import org.mozilla.fenix.theme.FirefoxTheme
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
|
||||
|
@ -111,6 +114,7 @@ class BrowserToolbarCFRPresenter(
|
|||
true -> TrackingProtection.tcpCfrExplicitDismissal.record(NoExtras())
|
||||
false -> TrackingProtection.tcpCfrImplicitDismissal.record(NoExtras())
|
||||
}
|
||||
tryToShowCookieBannerDialogIfNeeded()
|
||||
},
|
||||
) {
|
||||
Text(
|
||||
|
@ -137,4 +141,15 @@ class BrowserToolbarCFRPresenter(
|
|||
TrackingProtection.tcpCfrShown.record(NoExtras())
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
internal fun tryToShowCookieBannerDialogIfNeeded() {
|
||||
browserStore.state.selectedTab?.let { tab ->
|
||||
CookieBannerReEngagementDialogUtils.tryToShowReEngagementDialog(
|
||||
settings = settings,
|
||||
status = tab.cookieBanner,
|
||||
navController = toolbar.findNavController(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -167,8 +167,11 @@ class ExternalAppBrowserFragment : BaseBrowserFragment(), UserInteractionHandler
|
|||
val cookieBannersStorage = requireComponents.core.cookieBannersStorage
|
||||
requireComponents.useCases.trackingProtectionUseCases.containsException(tab.id) { contains ->
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
val hasException =
|
||||
val hasException = if (requireContext().settings().shouldUseCookieBanner) {
|
||||
cookieBannersStorage.hasException(tab.content.url, tab.content.private)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
runIfFragmentIsAttached {
|
||||
val directions = ExternalAppBrowserFragmentDirections
|
||||
|
|
|
@ -6,6 +6,7 @@ package org.mozilla.fenix.settings
|
|||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import org.mozilla.fenix.ext.settings
|
||||
|
||||
/**
|
||||
* Cookie banners switch preference with a learn more link.
|
||||
|
@ -18,4 +19,8 @@ class CookieBannersSwitchPreference(context: Context, attrs: AttributeSet?) :
|
|||
SupportUtils.SumoTopic.COOKIE_BANNER,
|
||||
)
|
||||
}
|
||||
|
||||
override fun getSwitchValue(): Boolean {
|
||||
return context.settings().shouldUseCookieBanner
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ package org.mozilla.fenix.settings
|
|||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.widget.SwitchCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.preference.PreferenceViewHolder
|
||||
import androidx.preference.SwitchPreferenceCompat
|
||||
|
@ -28,6 +29,12 @@ abstract class LearnMoreSwitchPreference(context: Context, attrs: AttributeSet?)
|
|||
override fun onBindViewHolder(holder: PreferenceViewHolder) {
|
||||
super.onBindViewHolder(holder)
|
||||
|
||||
val switch = holder.findViewById(R.id.learn_more_switch) as SwitchCompat
|
||||
|
||||
switch.run {
|
||||
isChecked = getSwitchValue()
|
||||
}
|
||||
|
||||
getDescription()?.let {
|
||||
val summaryView = holder.findViewById(android.R.id.summary) as TextView
|
||||
summaryView.text = it
|
||||
|
@ -62,4 +69,9 @@ abstract class LearnMoreSwitchPreference(context: Context, attrs: AttributeSet?)
|
|||
* Returns the URL that should be used when the learn more link is clicked.
|
||||
*/
|
||||
abstract fun getLearnMoreUrl(): String
|
||||
|
||||
/**
|
||||
* Indicates the value which the switch widget should show.
|
||||
*/
|
||||
abstract fun getSwitchValue(): Boolean
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import mozilla.components.concept.engine.permission.SitePermissions
|
|||
import org.mozilla.fenix.browser.BrowserFragmentDirections
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.runIfFragmentIsAttached
|
||||
import org.mozilla.fenix.ext.settings
|
||||
|
||||
/**
|
||||
* [ConnectionDetailsController] controller.
|
||||
|
@ -50,8 +51,11 @@ class DefaultConnectionDetailsController(
|
|||
getCurrentTab()?.let { tab ->
|
||||
context.components.useCases.trackingProtectionUseCases.containsException(tab.id) { contains ->
|
||||
ioScope.launch {
|
||||
val hasException =
|
||||
val hasException = if (context.settings().shouldUseCookieBanner) {
|
||||
cookieBannersStorage.hasException(tab.content.url, tab.content.private)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
fragment.runIfFragmentIsAttached {
|
||||
navController().popBackStack()
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.mozilla.fenix.GleanMetrics.CookieBanners
|
|||
import org.mozilla.fenix.browser.BrowserFragmentDirections
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.runIfFragmentIsAttached
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.trackingprotection.ProtectionsAction
|
||||
import org.mozilla.fenix.trackingprotection.ProtectionsStore
|
||||
|
||||
|
@ -72,8 +73,11 @@ class DefaultCookieBannerDetailsController(
|
|||
getCurrentTab()?.let { tab ->
|
||||
context.components.useCases.trackingProtectionUseCases.containsException(tab.id) { contains ->
|
||||
ioScope.launch {
|
||||
val hasException =
|
||||
val hasException = if (context.settings().shouldUseCookieBanner) {
|
||||
cookieBannersStorage.hasException(tab.content.url, tab.content.private)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
fragment.runIfFragmentIsAttached {
|
||||
navController().popBackStack()
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.fenix.settings.quicksettings.protections.cookiebanners.dialog
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.compose.ui.platform.ComposeView
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import mozilla.components.concept.engine.EngineSession.CookieBannerHandlingMode.REJECT_OR_ACCEPT_ALL
|
||||
import mozilla.components.concept.engine.Settings
|
||||
import mozilla.telemetry.glean.private.NoExtras
|
||||
import org.mozilla.fenix.GleanMetrics.CookieBanners
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.FenixSnackbar
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.getRootView
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.theme.FirefoxTheme
|
||||
|
||||
/**
|
||||
* Displays a cookie banner dialog fragment that contains the dialog compose and his logic.
|
||||
*/
|
||||
class CookieBannerReEngagementDialog : DialogFragment() {
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?,
|
||||
): View = ComposeView(requireContext()).apply {
|
||||
CookieBanners.visitedReEngagementDialog.record(NoExtras())
|
||||
|
||||
setContent {
|
||||
FirefoxTheme {
|
||||
val cookieBannerDialogSelectedVariant =
|
||||
CookieBannerReEngagementDialogUtils.getCookieBannerDialogVariants(requireContext())
|
||||
CookieBannerReEngagementDialogCompose(
|
||||
dialogTitle = cookieBannerDialogSelectedVariant.title,
|
||||
dialogText = cookieBannerDialogSelectedVariant.message,
|
||||
allowButtonText = cookieBannerDialogSelectedVariant.positiveTextButton,
|
||||
declineButtonText = getString(R.string.reduce_cookie_banner_dialog_not_now_button),
|
||||
onAllowButtonClicked = {
|
||||
CookieBanners.allowReEngagementDialog.record(NoExtras())
|
||||
requireContext().settings().shouldUseCookieBanner = true
|
||||
getEngineSettings().cookieBannerHandlingModePrivateBrowsing = REJECT_OR_ACCEPT_ALL
|
||||
getEngineSettings().cookieBannerHandlingMode = REJECT_OR_ACCEPT_ALL
|
||||
reload()
|
||||
requireContext().getRootView()?.let {
|
||||
FenixSnackbar.make(
|
||||
view = it,
|
||||
duration = FenixSnackbar.LENGTH_LONG,
|
||||
isDisplayedWithBrowserToolbar = true,
|
||||
)
|
||||
.setText(getString(R.string.reduce_cookie_banner_dialog_snackbar_text))
|
||||
.show()
|
||||
}
|
||||
dismiss()
|
||||
},
|
||||
onNotNowButtonClicked = {
|
||||
CookieBanners.notNowReEngagementDialog.record(NoExtras())
|
||||
dismiss()
|
||||
},
|
||||
onCloseButtonClicked = {
|
||||
requireContext().settings().userOptOutOfReEngageCookieBannerDialog = true
|
||||
CookieBanners.optOutReEngagementDialog.record(NoExtras())
|
||||
dismiss()
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getEngineSettings(): Settings {
|
||||
return requireContext().components.core.engine.settings
|
||||
}
|
||||
|
||||
private fun reload() {
|
||||
return requireContext().components.useCases.sessionUseCases.reload()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,156 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.fenix.settings.quicksettings.protections.cookiebanners.dialog
|
||||
|
||||
import android.content.res.Configuration.UI_MODE_NIGHT_NO
|
||||
import android.content.res.Configuration.UI_MODE_NIGHT_YES
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.IconButton
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Surface
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.theme.FirefoxTheme
|
||||
import org.mozilla.fenix.theme.defaultTypography
|
||||
|
||||
@Composable
|
||||
@Preview(uiMode = UI_MODE_NIGHT_YES)
|
||||
@Preview(uiMode = UI_MODE_NIGHT_NO)
|
||||
private fun CookieBannerReEngagementDialogComposePreview() {
|
||||
FirefoxTheme {
|
||||
CookieBannerReEngagementDialogCompose(
|
||||
dialogTitle = "Cookie banners begone!",
|
||||
dialogText =
|
||||
"Automatically reject cookie requests, when possible. Otherwise, " +
|
||||
"accept all cookies to dismiss cookie banners.",
|
||||
onAllowButtonClicked = {},
|
||||
onNotNowButtonClicked = {},
|
||||
onCloseButtonClicked = {},
|
||||
allowButtonText = "Dismiss banners",
|
||||
declineButtonText = "NOT NOW",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the cookie banner reducer dialog
|
||||
*/
|
||||
@Suppress("LongParameterList", "LongMethod")
|
||||
@Composable
|
||||
fun CookieBannerReEngagementDialogCompose(
|
||||
dialogTitle: String,
|
||||
dialogText: String,
|
||||
allowButtonText: String,
|
||||
declineButtonText: String,
|
||||
onCloseButtonClicked: () -> Unit,
|
||||
onAllowButtonClicked: () -> Unit,
|
||||
onNotNowButtonClicked: () -> Unit,
|
||||
) {
|
||||
Dialog(
|
||||
properties = DialogProperties(dismissOnBackPress = true, dismissOnClickOutside = false),
|
||||
onDismissRequest = onNotNowButtonClicked,
|
||||
) {
|
||||
Surface(
|
||||
color = Color.Transparent,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight()
|
||||
.clip(RoundedCornerShape(8.dp))
|
||||
.background(color = FirefoxTheme.colors.layer1),
|
||||
) {
|
||||
Column {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.padding(
|
||||
top = 24.dp,
|
||||
start = 24.dp,
|
||||
end = 24.dp,
|
||||
bottom = 8.dp,
|
||||
),
|
||||
color = FirefoxTheme.colors.textPrimary,
|
||||
text = dialogTitle,
|
||||
style = defaultTypography.headline7,
|
||||
)
|
||||
IconButton(
|
||||
modifier = Modifier
|
||||
.size(48.dp),
|
||||
onClick = onCloseButtonClicked,
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(R.drawable.mozac_ic_close),
|
||||
contentDescription = stringResource(R.string.content_description_close_button),
|
||||
tint = FirefoxTheme.colors.iconPrimary,
|
||||
)
|
||||
}
|
||||
}
|
||||
Text(
|
||||
modifier = Modifier.padding(horizontal = 24.dp),
|
||||
color = FirefoxTheme.colors.textPrimary,
|
||||
fontSize = 16.sp,
|
||||
text = dialogText,
|
||||
style = defaultTypography.body1,
|
||||
)
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(end = 24.dp, bottom = 12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(
|
||||
space = 8.dp,
|
||||
alignment = Alignment.End,
|
||||
),
|
||||
) {
|
||||
TextButton(
|
||||
onClick = onNotNowButtonClicked,
|
||||
shape = MaterialTheme.shapes.large,
|
||||
) {
|
||||
Text(
|
||||
text = declineButtonText.uppercase(),
|
||||
fontSize = 14.sp,
|
||||
style = MaterialTheme.typography.button,
|
||||
)
|
||||
}
|
||||
TextButton(
|
||||
onClick = onAllowButtonClicked,
|
||||
shape = MaterialTheme.shapes.large,
|
||||
) {
|
||||
Text(
|
||||
text = allowButtonText.uppercase(),
|
||||
fontSize = 14.sp,
|
||||
style = MaterialTheme.typography.button,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.fenix.settings.quicksettings.protections.cookiebanners.dialog
|
||||
|
||||
import android.content.Context
|
||||
import androidx.navigation.NavController
|
||||
import mozilla.components.concept.engine.EngineSession.CookieBannerHandlingStatus
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.browser.BrowserFragmentDirections
|
||||
import org.mozilla.fenix.ext.nav
|
||||
import org.mozilla.fenix.nimbus.CookieBannersSection
|
||||
import org.mozilla.fenix.nimbus.FxNimbus
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
|
||||
private const val CONTROL_VARIANT = 0
|
||||
private const val VARIANT_ONE = 1
|
||||
private const val VARIANT_TWO = 2
|
||||
|
||||
/**
|
||||
* An utility object for interacting with the re-engagement cookie banner dialog.
|
||||
*/
|
||||
object CookieBannerReEngagementDialogUtils {
|
||||
/**
|
||||
* Returns a the current [CookieBannerDialogVariant] to the given nimbus experiment.
|
||||
*/
|
||||
fun getCookieBannerDialogVariants(context: Context): CookieBannerDialogVariant {
|
||||
val textVariant =
|
||||
FxNimbus.features.cookieBanners.value().sectionsEnabled[CookieBannersSection.DIALOG_TEXT_VARIANT]
|
||||
return when (textVariant) {
|
||||
CONTROL_VARIANT -> CookieBannerDialogVariant(
|
||||
title = context.getString(R.string.reduce_cookie_banner_control_experiment_dialog_title),
|
||||
message = context.getString(
|
||||
R.string.reduce_cookie_banner_control_experiment_dialog_body,
|
||||
),
|
||||
positiveTextButton = context.getString(
|
||||
R.string.reduce_cookie_banner_control_experiment_dialog_change_setting_button,
|
||||
),
|
||||
)
|
||||
VARIANT_ONE -> CookieBannerDialogVariant(
|
||||
title = context.getString(R.string.reduce_cookie_banner_variant_1_experiment_dialog_title),
|
||||
message = context.getString(
|
||||
R.string.reduce_cookie_banner_variant_1_experiment_dialog_body,
|
||||
context.getString(R.string.app_name),
|
||||
),
|
||||
positiveTextButton = context.getString(
|
||||
R.string.reduce_cookie_banner_variant_1_experiment_dialog_change_setting_button,
|
||||
),
|
||||
)
|
||||
VARIANT_TWO -> CookieBannerDialogVariant(
|
||||
title = context.getString(R.string.reduce_cookie_banner_variant_2_experiment_dialog_title),
|
||||
message = context.getString(
|
||||
R.string.reduce_cookie_banner_variant_2_experiment_dialog_body,
|
||||
context.getString(R.string.app_name),
|
||||
),
|
||||
positiveTextButton = context.getString(
|
||||
R.string.reduce_cookie_banner_variant_2_experiment_dialog_change_setting_button,
|
||||
),
|
||||
)
|
||||
else -> {
|
||||
CookieBannerDialogVariant(
|
||||
title = context.getString(R.string.reduce_cookie_banner_control_experiment_dialog_title),
|
||||
message = context.getString(
|
||||
R.string.reduce_cookie_banner_control_experiment_dialog_body,
|
||||
),
|
||||
positiveTextButton = context.getString(
|
||||
R.string.reduce_cookie_banner_control_experiment_dialog_change_setting_button,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to show the re-engagement cookie banner dialog, when the right conditions are met, o
|
||||
* otherwise the dialog won't show.
|
||||
*/
|
||||
fun tryToShowReEngagementDialog(
|
||||
settings: Settings,
|
||||
status: CookieBannerHandlingStatus,
|
||||
navController: NavController,
|
||||
) {
|
||||
if (status == CookieBannerHandlingStatus.DETECTED &&
|
||||
settings.shouldCookieBannerReEngagementDialog()
|
||||
) {
|
||||
settings.cookieBannerDetectedPreviously = true
|
||||
val directions =
|
||||
BrowserFragmentDirections.actionBrowserFragmentToCookieBannerDialogFragment()
|
||||
navController.nav(R.id.browserFragment, directions)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Data class for cookie banner dialog variant
|
||||
* @property title of the dialog
|
||||
* @property message of the dialog
|
||||
* @property positiveTextButton indicates the text of the positive button of the dialog
|
||||
*/
|
||||
data class CookieBannerDialogVariant(
|
||||
val title: String,
|
||||
val message: String,
|
||||
val positiveTextButton: String,
|
||||
)
|
||||
}
|
|
@ -17,6 +17,7 @@ import mozilla.components.concept.engine.permission.SitePermissions
|
|||
import org.mozilla.fenix.browser.BrowserFragmentDirections
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.runIfFragmentIsAttached
|
||||
import org.mozilla.fenix.ext.settings
|
||||
|
||||
/**
|
||||
* Interactor for the tracking protection panel
|
||||
|
@ -53,8 +54,11 @@ class TrackingProtectionPanelInteractor(
|
|||
getCurrentTab()?.let { tab ->
|
||||
context.components.useCases.trackingProtectionUseCases.containsException(tab.id) { contains ->
|
||||
ioScope.launch {
|
||||
val hasException =
|
||||
val hasException = if (context.settings().shouldUseCookieBanner) {
|
||||
cookieBannersStorage.hasException(tab.content.url, tab.content.private)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
fragment.runIfFragmentIsAttached {
|
||||
navController().popBackStack()
|
||||
|
|
|
@ -544,11 +544,43 @@ class Settings(private val appContext: Context) : PreferencesHolder {
|
|||
var shouldUseCookieBanner by lazyFeatureFlagPreference(
|
||||
appContext.getPreferenceKey(R.string.pref_key_cookie_banner_v1),
|
||||
featureFlag = true,
|
||||
default = { cookieBannersSection[CookieBannersSection.FEATURE_SETTING_VALUE] == true },
|
||||
default = { cookieBannersSection[CookieBannersSection.FEATURE_SETTING_VALUE] == 1 },
|
||||
)
|
||||
|
||||
var userOptOutOfReEngageCookieBannerDialog by booleanPreference(
|
||||
appContext.getPreferenceKey(R.string.pref_key_cookie_banner_re_engage_dialog_dismissed),
|
||||
default = false,
|
||||
)
|
||||
|
||||
var cookieBannerDetectedPreviously by booleanPreference(
|
||||
appContext.getPreferenceKey(R.string.pref_key_cookie_banner_first_banner_detected),
|
||||
default = false,
|
||||
)
|
||||
|
||||
val shouldShowCookieBannerUI: Boolean
|
||||
get() = cookieBannersSection[CookieBannersSection.FEATURE_UI] == true
|
||||
get() = cookieBannersSection[CookieBannersSection.FEATURE_UI] == 1
|
||||
|
||||
/**
|
||||
* Indicates after how many hours a cookie banner dialog should be shown again
|
||||
*/
|
||||
@VisibleForTesting
|
||||
internal val timerForCookieBannerDialog: Long
|
||||
get() = 60 * 60 * 1000L *
|
||||
(cookieBannersSection[CookieBannersSection.DIALOG_RE_ENGAGE_TIME] ?: 4)
|
||||
|
||||
/**
|
||||
* Indicates if we should should show the cookie banner dialog that invites the user to turn-on
|
||||
* the setting.
|
||||
*/
|
||||
fun shouldCookieBannerReEngagementDialog(): Boolean {
|
||||
val shouldShowDialog =
|
||||
shouldShowCookieBannerUI && !userOptOutOfReEngageCookieBannerDialog && !shouldUseCookieBanner
|
||||
return if (!shouldShowTotalCookieProtectionCFR && shouldShowDialog) {
|
||||
!cookieBannerDetectedPreviously || timeNowInMillis() - lastBrowseActivity >= timerForCookieBannerDialog
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Declared as a function for performance purposes. This could be declared as a variable using
|
||||
|
@ -1293,7 +1325,7 @@ class Settings(private val appContext: Context) : PreferencesHolder {
|
|||
get() =
|
||||
FxNimbus.features.mr2022.value().sectionsEnabled
|
||||
|
||||
private val cookieBannersSection: Map<CookieBannersSection, Boolean>
|
||||
private val cookieBannersSection: Map<CookieBannersSection, Int>
|
||||
get() =
|
||||
FxNimbus.features.cookieBanners.value().sectionsEnabled
|
||||
|
||||
|
@ -1458,7 +1490,11 @@ class Settings(private val appContext: Context) : PreferencesHolder {
|
|||
fun getCookieBannerHandling(): CookieBannerHandlingMode {
|
||||
return when (shouldUseCookieBanner) {
|
||||
true -> CookieBannerHandlingMode.REJECT_OR_ACCEPT_ALL
|
||||
false -> CookieBannerHandlingMode.DISABLED
|
||||
false -> if (shouldShowCookieBannerUI && !userOptOutOfReEngageCookieBannerDialog) {
|
||||
CookieBannerHandlingMode.DETECT_ONLY
|
||||
} else {
|
||||
CookieBannerHandlingMode.DISABLED
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -55,12 +55,14 @@
|
|||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@android:id/widget_frame"
|
||||
<androidx.appcompat.widget.SwitchCompat
|
||||
android:id="@+id/learn_more_switch"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="end|center_vertical"
|
||||
android:minWidth="58dp"
|
||||
android:orientation="vertical" />
|
||||
android:minHeight="48dp"
|
||||
android:textColor="@color/state_list_text_color"
|
||||
android:textOff="@string/studies_off"
|
||||
android:textOn="@string/studies_on" />
|
||||
|
||||
</LinearLayout>
|
||||
|
|
|
@ -259,6 +259,9 @@
|
|||
<action
|
||||
android:id="@+id/action_browserFragment_to_quickSettingsSheetDialogFragment"
|
||||
app:destination="@id/quickSettingsSheetDialogFragment" />
|
||||
<action
|
||||
android:id="@+id/action_browserFragment_to_cookieBannerDialogFragment"
|
||||
app:destination="@id/cookieBannerDialogFragment" />
|
||||
</fragment>
|
||||
|
||||
<fragment
|
||||
|
@ -960,6 +963,9 @@
|
|||
android:name="isCookieHandlingEnabled"
|
||||
app:argType="boolean" />
|
||||
</dialog>
|
||||
<dialog
|
||||
android:id="@+id/cookieBannerDialogFragment"
|
||||
android:name="org.mozilla.fenix.settings.quicksettings.protections.cookiebanners.dialog.CookieBannerReEngagementDialog" />
|
||||
<fragment
|
||||
android:id="@+id/accountProblemFragment"
|
||||
android:name="org.mozilla.fenix.settings.account.AccountProblemFragment">
|
||||
|
|
|
@ -151,6 +151,8 @@
|
|||
|
||||
<!-- Cookie Banner Reduction Settings-->
|
||||
<string name="pref_key_cookie_banner_settings" translatable="false">pref_key_cookie_banner_settings</string>
|
||||
<string name="pref_key_cookie_banner_re_engage_dialog_dismissed" translatable="false">pref_key_cookie_banner_re_engage_dialog_dismissed</string>
|
||||
<string name="pref_key_cookie_banner_first_banner_detected" translatable="false">pref_key_cookie_banner_first_banner_detected</string>
|
||||
<string name="pref_key_cookie_banner_v1" translatable="false">pref_key_cookie_banner_v1</string>
|
||||
|
||||
<!-- Tracking Protection Settings -->
|
||||
|
|
|
@ -346,21 +346,23 @@
|
|||
<!-- Body text for the dialog use on the control branch of the experiment to determine which context users engaged the most -->
|
||||
<string name="reduce_cookie_banner_control_experiment_dialog_body" tools:ignore="UnusedResources">Automatically reject cookie requests, when possible. Otherwise, accept all cookies to dismiss cookie banners.</string>
|
||||
<!-- Remind me later text button for the onboarding dialog -->
|
||||
<string name="reduce_cookie_banner_dialog_not_now_button" tools:ignore="UnusedResources">Not Now</string>
|
||||
<string name="reduce_cookie_banner_dialog_not_now_button">Not Now</string>
|
||||
<!-- Change setting text button, for the dialog use on the control branch of the experiment to determine which context users engaged the most -->
|
||||
<string name="reduce_cookie_banner_control_experiment_dialog_change_setting_button" tools:ignore="UnusedResources">Dismiss banners</string>
|
||||
<string name="reduce_cookie_banner_control_experiment_dialog_change_setting_button">Dismiss banners</string>
|
||||
<!-- Snack text for the cookie banner dialog, after user hit the dismiss banner button -->
|
||||
<string name="reduce_cookie_banner_dialog_snackbar_text">You’ll see fewer cookie requests</string>
|
||||
<!-- Title text for the dialog use on the variant 1 branch of the experiment to determine which context users engaged the most -->
|
||||
<string name="reduce_cookie_banner_variant_1_experiment_dialog_title" tools:ignore="UnusedResources">See fewer cookie pop-ups</string>
|
||||
<!-- Body text for the dialog use on the variant 1 branch of the experiment to determine which context users engaged the most -->
|
||||
<string name="reduce_cookie_banner_variant_1_experiment_dialog_body" tools:ignore="UnusedResources">Automatically answer cookie pop-ups for distraction-free browsing. Firefox will reject all requests if possible, or accept all if not.</string>
|
||||
<string name="reduce_cookie_banner_variant_1_experiment_dialog_title">See fewer cookie pop-ups</string>
|
||||
<!-- Body text for the dialog use on the variant 1 branch of the experiment to determine which context users engaged the most. The first parameter is the application name. -->
|
||||
<string name="reduce_cookie_banner_variant_1_experiment_dialog_body">Automatically answer cookie pop-ups for distraction-free browsing. %1$s will reject all requests if possible, or accept all if not.</string>
|
||||
<!-- Change setting text button, for the onboarding dialog use on the variant 1 branch of the experiment to determine which context users engaged the most -->
|
||||
<string name="reduce_cookie_banner_variant_1_experiment_dialog_change_setting_button" tools:ignore="UnusedResources">Dismiss Pop-ups</string>
|
||||
<string name="reduce_cookie_banner_variant_1_experiment_dialog_change_setting_button">Dismiss Pop-ups</string>
|
||||
<!-- Title text for the dialog use on the variant 2 branch of the experiment to determine which context users engaged the most -->
|
||||
<string name="reduce_cookie_banner_variant_2_experiment_dialog_title" tools:ignore="UnusedResources">Cookie Banner Reduction</string>
|
||||
<!-- Body text for the dialog use on the variant 2 branch of the experiment to determine which context users engaged the most -->
|
||||
<string name="reduce_cookie_banner_variant_2_experiment_dialog_body" tools:ignore="UnusedResources">Allow Firefox to decline a site’s cookie consent request if possible or accept cookie access when not possible?</string>
|
||||
<string name="reduce_cookie_banner_variant_2_experiment_dialog_title">Cookie Banner Reduction</string>
|
||||
<!-- Body text for the dialog use on the variant 2 branch of the experiment to determine which context users engaged the most. The first parameter is the application name. -->
|
||||
<string name="reduce_cookie_banner_variant_2_experiment_dialog_body">Allow %1$s to decline a site’s cookie consent request if possible or accept cookie access when not possible?</string>
|
||||
<!-- Change setting text button, for the dialog use on the variant 2 branch of the experiment to determine which context users engaged the most -->
|
||||
<string name="reduce_cookie_banner_variant_2_experiment_dialog_change_setting_button" tools:ignore="UnusedResources">Allow</string>
|
||||
<string name="reduce_cookie_banner_variant_2_experiment_dialog_change_setting_button">Allow</string>
|
||||
|
||||
<!-- Description of the preference to enable "HTTPS-Only" mode. -->
|
||||
<string name="preferences_https_only_summary">Automatically attempts to connect to sites using HTTPS encryption protocol for increased security.</string>
|
||||
|
|
|
@ -221,6 +221,7 @@ class BrowserToolbarCFRPresenterTest {
|
|||
val presenter = createPresenter(
|
||||
anchor = mockk(relaxed = true),
|
||||
)
|
||||
every { presenter.tryToShowCookieBannerDialogIfNeeded() } just Runs
|
||||
|
||||
presenter.showTcpCfr()
|
||||
|
||||
|
@ -231,6 +232,9 @@ class BrowserToolbarCFRPresenterTest {
|
|||
assertNull(TrackingProtection.tcpCfrImplicitDismissal.testGetValue())
|
||||
presenter.tcpCfrPopup!!.onDismiss.invoke(false)
|
||||
assertNotNull(TrackingProtection.tcpCfrImplicitDismissal.testGetValue())
|
||||
verify {
|
||||
presenter.tryToShowCookieBannerDialogIfNeeded()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -260,12 +264,14 @@ class BrowserToolbarCFRPresenterTest {
|
|||
every { findViewById<View>(R.id.mozac_browser_toolbar_security_indicator) } returns anchor
|
||||
},
|
||||
sessionId: String? = null,
|
||||
) = BrowserToolbarCFRPresenter(
|
||||
context = context,
|
||||
browserStore = browserStore,
|
||||
settings = settings,
|
||||
toolbar = toolbar,
|
||||
sessionId = sessionId,
|
||||
) = spyk(
|
||||
BrowserToolbarCFRPresenter(
|
||||
context = context,
|
||||
browserStore = browserStore,
|
||||
settings = settings,
|
||||
toolbar = toolbar,
|
||||
sessionId = sessionId,
|
||||
),
|
||||
)
|
||||
|
||||
private fun createBrowserStore(
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.junit.Rule
|
|||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||
|
||||
@RunWith(FenixRobolectricTestRunner::class)
|
||||
|
@ -87,6 +88,8 @@ class DefaultConnectionDetailsControllerTest {
|
|||
|
||||
@Test
|
||||
fun `WHEN handleBackPressed is called THEN should call popBackStack and navigate`() {
|
||||
every { context.settings().shouldUseCookieBanner } returns true
|
||||
|
||||
controller.handleBackPressed()
|
||||
|
||||
verify {
|
||||
|
|
|
@ -43,6 +43,7 @@ import org.junit.Test
|
|||
import org.junit.runner.RunWith
|
||||
import org.mozilla.fenix.GleanMetrics.CookieBanners
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||
import org.mozilla.fenix.trackingprotection.ProtectionsAction
|
||||
import org.mozilla.fenix.trackingprotection.ProtectionsStore
|
||||
|
@ -131,6 +132,8 @@ internal class DefaultCookieBannerDetailsControllerTest {
|
|||
|
||||
@Test
|
||||
fun `WHEN handleBackPressed is called THEN should call popBackStack and navigate`() {
|
||||
every { context.settings().shouldUseCookieBanner } returns true
|
||||
|
||||
controller.handleBackPressed()
|
||||
|
||||
verify {
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.junit.Rule
|
|||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||
|
||||
@RunWith(FenixRobolectricTestRunner::class)
|
||||
|
@ -139,6 +140,8 @@ class TrackingProtectionPanelInteractorTest {
|
|||
|
||||
@Test
|
||||
fun `WHEN onBackPressed is called THEN call popBackStack and navigate`() = runTestOnMain {
|
||||
every { context.settings().shouldUseCookieBanner } returns true
|
||||
|
||||
interactor.onBackPressed()
|
||||
|
||||
coVerify {
|
||||
|
|
|
@ -219,25 +219,31 @@ features:
|
|||
variables:
|
||||
sections-enabled:
|
||||
description: "This property provides a lookup table of whether or not the given section should be enabled."
|
||||
type: Map<CookieBannersSection, Boolean>
|
||||
type: Map<CookieBannersSection, Int>
|
||||
default:
|
||||
{
|
||||
"feature-ui": false,
|
||||
"feature-setting-value": false,
|
||||
"feature-ui": 0,
|
||||
"feature-setting-value": 0,
|
||||
"dialog-re-engage-time": 4,
|
||||
"dialog-text-variant": 0,
|
||||
}
|
||||
defaults:
|
||||
- channel: developer
|
||||
value: {
|
||||
"sections-enabled": {
|
||||
"feature-ui": true,
|
||||
"feature-setting-value": false,
|
||||
"feature-ui": 1,
|
||||
"feature-setting-value": 0,
|
||||
"dialog-re-engage-time": 4,
|
||||
"dialog-text-variant": 0,
|
||||
}
|
||||
}
|
||||
- channel: nightly
|
||||
value: {
|
||||
"sections-enabled": {
|
||||
"feature-ui": true,
|
||||
"feature-setting-value": false,
|
||||
"feature-ui": 1,
|
||||
"feature-setting-value": 0,
|
||||
"dialog-re-engage-time": 4,
|
||||
"dialog-text-variant": 0,
|
||||
}
|
||||
}
|
||||
unified-search:
|
||||
|
@ -409,3 +415,7 @@ types:
|
|||
description: Indicates if the user interfaces should be visible.
|
||||
feature-setting-value:
|
||||
description: Indicates if the cookie handling setting should be enabled.
|
||||
dialog-re-engage-time:
|
||||
description: Indicates after how many hours of interaction, the dialog should show again.
|
||||
dialog-text-variant:
|
||||
description: Indicates which text variant should be used in the dialog.
|
||||
|
|
Loading…
Reference in New Issue