mirror of
https://github.com/fork-maintainers/iceraven-browser
synced 2024-11-15 18:12:54 +00:00
Bug 1859393 - Add CFR when the first cookie banner gets cleared.
This commit is contained in:
parent
6fca903727
commit
1cce998212
@ -8530,7 +8530,38 @@ cookie_banners:
|
||||
metadata:
|
||||
tags:
|
||||
- Privacy&Security
|
||||
|
||||
cfr_shown:
|
||||
type: event
|
||||
description: The cookie banner cfr has been shown
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1859393
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1859393#c2
|
||||
data_sensitivity:
|
||||
- interaction
|
||||
notification_emails:
|
||||
- android-probes@mozilla.com
|
||||
expires: never
|
||||
metadata:
|
||||
tags:
|
||||
- Privacy&Security
|
||||
cfr_dismissal:
|
||||
type: event
|
||||
description: |
|
||||
The cookie banners CFR was dismissed by the user by interacting
|
||||
with the outside of the popup
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1859393
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1859393#c2
|
||||
data_sensitivity:
|
||||
- interaction
|
||||
notification_emails:
|
||||
- android-probes@mozilla.com
|
||||
expires: never
|
||||
metadata:
|
||||
tags:
|
||||
- Privacy&Security
|
||||
site_permissions:
|
||||
prompt_shown:
|
||||
type: event
|
||||
|
@ -8,9 +8,17 @@ import android.content.Context
|
||||
import android.view.View
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.semantics.testTag
|
||||
@ -34,8 +42,11 @@ import mozilla.components.browser.toolbar.BrowserToolbar
|
||||
import mozilla.components.compose.cfr.CFRPopup
|
||||
import mozilla.components.compose.cfr.CFRPopup.PopupAlignment.INDICATOR_CENTERED_IN_ANCHOR
|
||||
import mozilla.components.compose.cfr.CFRPopupProperties
|
||||
import mozilla.components.concept.engine.EngineSession.CookieBannerHandlingStatus
|
||||
import mozilla.components.lib.state.ext.flowScoped
|
||||
import mozilla.components.service.glean.private.NoExtras
|
||||
import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifAnyChanged
|
||||
import org.mozilla.fenix.GleanMetrics.CookieBanners
|
||||
import org.mozilla.fenix.GleanMetrics.Shopping
|
||||
import org.mozilla.fenix.GleanMetrics.TrackingProtection
|
||||
import org.mozilla.fenix.R
|
||||
@ -109,6 +120,24 @@ class BrowserToolbarCFRPresenter(
|
||||
}
|
||||
}
|
||||
}
|
||||
ToolbarCFR.COOKIE_BANNERS -> {
|
||||
scope = browserStore.flowScoped { flow ->
|
||||
flow.mapNotNull { it.findCustomTabOrSelectedTab(sessionId) }
|
||||
.ifAnyChanged { tab ->
|
||||
arrayOf(
|
||||
tab.cookieBanner,
|
||||
)
|
||||
}
|
||||
.filter {
|
||||
it.content.private && it.cookieBanner == CookieBannerHandlingStatus.HANDLED
|
||||
}
|
||||
.collect {
|
||||
scope?.cancel()
|
||||
settings.shouldShowCookieBannersCFR = false
|
||||
showCookieBannersCFR()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ToolbarCFR.SHOPPING, ToolbarCFR.SHOPPING_OPTED_IN -> {
|
||||
scope = browserStore.flowScoped { flow ->
|
||||
@ -190,6 +219,10 @@ class BrowserToolbarCFRPresenter(
|
||||
settings.openTabsCount >= CFR_MINIMUM_NUMBER_OPENED_TABS
|
||||
) -> ToolbarCFR.TCP
|
||||
|
||||
isPrivate && settings.shouldShowCookieBannersCFR && settings.shouldUseCookieBannerPrivateMode -> {
|
||||
ToolbarCFR.COOKIE_BANNERS
|
||||
}
|
||||
|
||||
shoppingExperienceFeature.isEnabled &&
|
||||
settings.shouldShowReviewQualityCheckCFR -> whichShoppingCFR()
|
||||
|
||||
@ -325,6 +358,64 @@ class BrowserToolbarCFRPresenter(
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@Suppress("LongMethod")
|
||||
internal fun showCookieBannersCFR() {
|
||||
CFRPopup(
|
||||
anchor = toolbar.findViewById(
|
||||
R.id.mozac_browser_toolbar_security_indicator,
|
||||
),
|
||||
properties = CFRPopupProperties(
|
||||
popupAlignment = INDICATOR_CENTERED_IN_ANCHOR,
|
||||
popupBodyColors = listOf(
|
||||
getColor(context, R.color.fx_mobile_layer_color_gradient_end),
|
||||
getColor(context, R.color.fx_mobile_layer_color_gradient_start),
|
||||
),
|
||||
popupVerticalOffset = CFR_TO_ANCHOR_VERTICAL_PADDING.dp,
|
||||
dismissButtonColor = getColor(context, R.color.fx_mobile_icon_color_oncolor),
|
||||
indicatorDirection = if (settings.toolbarPosition == ToolbarPosition.TOP) {
|
||||
CFRPopup.IndicatorDirection.UP
|
||||
} else {
|
||||
CFRPopup.IndicatorDirection.DOWN
|
||||
},
|
||||
),
|
||||
onDismiss = {
|
||||
CookieBanners.cfrDismissal.record(NoExtras())
|
||||
},
|
||||
text = {
|
||||
FirefoxTheme {
|
||||
Column {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_cookies_disabled),
|
||||
contentDescription = null,
|
||||
tint = FirefoxTheme.colors.iconPrimary,
|
||||
)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text(
|
||||
text = context.getString(R.string.cookie_banner_cfr_title),
|
||||
color = FirefoxTheme.colors.textOnColorPrimary,
|
||||
style = FirefoxTheme.typography.subtitle2,
|
||||
)
|
||||
}
|
||||
Text(
|
||||
text = context.getString(R.string.cookie_banner_cfr_message),
|
||||
color = FirefoxTheme.colors.textOnColorPrimary,
|
||||
style = FirefoxTheme.typography.body2,
|
||||
modifier = Modifier.padding(top = 2.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
).run {
|
||||
popup = this
|
||||
show()
|
||||
CookieBanners.cfrShown.record(NoExtras())
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
internal fun showShoppingCFR(shouldShowOptedInCFR: Boolean) {
|
||||
CFRPopup(
|
||||
@ -395,5 +486,5 @@ class BrowserToolbarCFRPresenter(
|
||||
* The CFR to be shown in the toolbar.
|
||||
*/
|
||||
private enum class ToolbarCFR {
|
||||
TCP, SHOPPING, SHOPPING_OPTED_IN, ERASE, NONE
|
||||
TCP, SHOPPING, SHOPPING_OPTED_IN, ERASE, COOKIE_BANNERS, NONE
|
||||
}
|
||||
|
@ -778,6 +778,15 @@ class Settings(private val appContext: Context) : PreferencesHolder {
|
||||
default = { feltPrivateBrowsingEnabled },
|
||||
)
|
||||
|
||||
/**
|
||||
* Indicates if the cookie banners CRF should be shown.
|
||||
*/
|
||||
var shouldShowCookieBannersCFR by lazyFeatureFlagPreference(
|
||||
appContext.getPreferenceKey(R.string.pref_key_should_show_cookie_banners_action_popup),
|
||||
featureFlag = true,
|
||||
default = { shouldShowCookieBannerUI },
|
||||
)
|
||||
|
||||
val blockCookiesSelectionInCustomTrackingProtection by stringPreference(
|
||||
key = appContext.getPreferenceKey(R.string.pref_key_tracking_protection_custom_cookies_select),
|
||||
default = if (enabledTotalCookieProtection) {
|
||||
|
@ -275,6 +275,8 @@
|
||||
<string name="pref_key_should_show_total_cookie_protection_popup" translatable="false">pref_key_should_show_total_cookie_protection_popup</string>
|
||||
<!-- A value of `true` means the erase action popup has not been shown yet -->
|
||||
<string name="pref_key_should_show_erase_action_popup" translatable="false">pref_key_should_show_erase_action_popup</string>
|
||||
<!-- A value of `true` means the cookie banners handling action popup has not been shown yet -->
|
||||
<string name="pref_key_should_show_cookie_banners_action_popup" translatable="false">pref_key_should_show_cookie_banners_action_popup</string>
|
||||
|
||||
<string name="pref_key_debug_settings" translatable="false">pref_key_debug_settings</string>
|
||||
|
||||
|
@ -498,6 +498,10 @@
|
||||
<string name="reduce_cookie_banner_dialog_snackbar_text" moz:RemovedIn="121" tools:ignore="UnusedResources">You’ll see fewer cookie requests</string>
|
||||
<!-- Change setting text button, for the cookie banner re-engagement dialog -->
|
||||
<string name="reduce_cookie_banner_dialog_change_setting_button" moz:RemovedIn="121" tools:ignore="UnusedResources">Allow</string>
|
||||
<!--Title for the cookie banner re-engagement CFR -->
|
||||
<string name="cookie_banner_cfr_title">Firefox just refused cookies for you</string>
|
||||
<!--Message for the cookie banner re-engagement CFR -->
|
||||
<string name="cookie_banner_cfr_message">Less distractions, less cookies tracking you on this site.</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>
|
||||
|
@ -15,6 +15,7 @@ import io.mockk.verify
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.cancel
|
||||
import mozilla.components.browser.state.action.ContentAction
|
||||
import mozilla.components.browser.state.action.CookieBannerAction
|
||||
import mozilla.components.browser.state.action.TabListAction
|
||||
import mozilla.components.browser.state.state.BrowserState
|
||||
import mozilla.components.browser.state.state.CustomTabSessionState
|
||||
@ -23,6 +24,7 @@ import mozilla.components.browser.state.state.createCustomTab
|
||||
import mozilla.components.browser.state.state.createTab
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.browser.toolbar.BrowserToolbar
|
||||
import mozilla.components.concept.engine.EngineSession
|
||||
import mozilla.components.support.test.ext.joinBlocking
|
||||
import mozilla.components.support.test.robolectric.testContext
|
||||
import mozilla.components.support.test.rule.MainCoroutineRule
|
||||
@ -69,6 +71,40 @@ class BrowserToolbarCFRPresenterTest {
|
||||
verify { presenter.showTcpCfr() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN the cookie banners handling CFR should be shown for a custom tab WHEN the custom tab is fully loaded THEN the TCP CFR is shown`() {
|
||||
val privateTab = createTab(url = "", private = true)
|
||||
val browserStore = createBrowserStore(tab = privateTab, selectedTabId = privateTab.id)
|
||||
val settings: Settings = mockk(relaxed = true) {
|
||||
every { shouldShowTotalCookieProtectionCFR } returns false
|
||||
every { shouldShowReviewQualityCheckCFR } returns false
|
||||
every { reviewQualityCheckOptInTimeInMillis } returns System.currentTimeMillis()
|
||||
every { shouldShowEraseActionCFR } returns false
|
||||
every { shouldShowCookieBannersCFR } returns true
|
||||
every { shouldUseCookieBannerPrivateMode } returns true
|
||||
every { reviewQualityCheckCfrDisplayTimeInMillis } returns 0L
|
||||
}
|
||||
val presenter = createPresenter(
|
||||
isPrivate = true,
|
||||
browserStore = browserStore,
|
||||
settings = settings,
|
||||
)
|
||||
|
||||
presenter.start()
|
||||
|
||||
assertNotNull(presenter.scope)
|
||||
|
||||
browserStore.dispatch(
|
||||
CookieBannerAction.UpdateStatusAction(
|
||||
privateTab.id,
|
||||
EngineSession.CookieBannerHandlingStatus.HANDLED,
|
||||
),
|
||||
).joinBlocking()
|
||||
|
||||
verify { presenter.showCookieBannersCFR() }
|
||||
verify { settings.shouldShowCookieBannersCFR = false }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN the TCP CFR should be shown WHEN the current normal tab is fully loaded THEN the TCP CFR is shown`() {
|
||||
val normalTab = createTab(url = "", private = false)
|
||||
@ -457,6 +493,7 @@ class BrowserToolbarCFRPresenterTest {
|
||||
every { shouldShowTotalCookieProtectionCFR } returns true
|
||||
every { shouldShowEraseActionCFR } returns true
|
||||
every { openTabsCount } returns 5
|
||||
every { shouldShowCookieBannersCFR } returns true
|
||||
every { shouldShowReviewQualityCheckCFR } returns true
|
||||
},
|
||||
toolbar: BrowserToolbar = mockk {
|
||||
|
Loading…
Reference in New Issue
Block a user