For #19886 - Add navigation from quick settings to tracking protection panel

upstream-sync
Gabriel Luong 3 years ago committed by Arturo Mejia
parent 465f553ea8
commit cad0e110dd

@ -321,18 +321,22 @@ class BrowserFragment : BaseBrowserFragment(), UserInteractionHandler {
}
override fun navToQuickSettingsSheet(tab: SessionState, sitePermissions: SitePermissions?) {
val directions =
BrowserFragmentDirections.actionBrowserFragmentToQuickSettingsSheetDialogFragment(
sessionId = tab.id,
url = tab.content.url,
title = tab.content.title,
isSecured = tab.content.securityInfo.secure,
sitePermissions = sitePermissions,
gravity = getAppropriateLayoutGravity(),
certificateName = tab.content.securityInfo.issuer,
permissionHighlights = tab.content.permissionHighlights
)
nav(R.id.browserFragment, directions)
requireComponents.useCases.trackingProtectionUseCases.containsException(tab.id) { contains ->
val isTrackingProtectionEnabled = tab.trackingProtection.enabled && !contains
val directions =
BrowserFragmentDirections.actionBrowserFragmentToQuickSettingsSheetDialogFragment(
sessionId = tab.id,
url = tab.content.url,
title = tab.content.title,
isSecured = tab.content.securityInfo.secure,
sitePermissions = sitePermissions,
gravity = getAppropriateLayoutGravity(),
certificateName = tab.content.securityInfo.issuer,
permissionHighlights = tab.content.permissionHighlights,
isTrackingProtectionEnabled = isTrackingProtectionEnabled
)
nav(R.id.browserFragment, directions)
}
}
private val collectionStorageObserver = object : TabCollectionStorage.Observer {

@ -177,18 +177,21 @@ class ExternalAppBrowserFragment : BaseBrowserFragment(), UserInteractionHandler
}
override fun navToQuickSettingsSheet(tab: SessionState, sitePermissions: SitePermissions?) {
val directions = ExternalAppBrowserFragmentDirections
.actionGlobalQuickSettingsSheetDialogFragment(
sessionId = tab.id,
url = tab.content.url,
title = tab.content.title,
isSecured = tab.content.securityInfo.secure,
sitePermissions = sitePermissions,
gravity = getAppropriateLayoutGravity(),
certificateName = tab.content.securityInfo.issuer,
permissionHighlights = tab.content.permissionHighlights
)
nav(R.id.externalAppBrowserFragment, directions)
requireComponents.useCases.trackingProtectionUseCases.containsException(tab.id) { contains ->
val directions = ExternalAppBrowserFragmentDirections
.actionGlobalQuickSettingsSheetDialogFragment(
sessionId = tab.id,
url = tab.content.url,
title = tab.content.title,
isSecured = tab.content.securityInfo.secure,
sitePermissions = sitePermissions,
gravity = getAppropriateLayoutGravity(),
certificateName = tab.content.securityInfo.issuer,
permissionHighlights = tab.content.permissionHighlights,
isTrackingProtectionEnabled = tab.trackingProtection.enabled && !contains
)
nav(R.id.externalAppBrowserFragment, directions)
}
}
override fun getContextMenuCandidates(

@ -11,12 +11,15 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import mozilla.components.browser.state.selector.findTabOrCustomTab
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.feature.session.SessionUseCases.ReloadUrlUseCase
import mozilla.components.concept.engine.permission.SitePermissions
import mozilla.components.feature.session.SessionUseCases.ReloadUrlUseCase
import mozilla.components.feature.tabs.TabsUseCases.AddNewTabUseCase
import mozilla.components.support.base.feature.OnNeedToRequestPermissions
import mozilla.components.support.ktx.kotlin.getOrigin
import org.mozilla.fenix.R
import org.mozilla.fenix.components.PermissionStorage
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.nav
import org.mozilla.fenix.settings.PhoneFeature
import org.mozilla.fenix.settings.quicksettings.ext.shouldBeEnabled
import org.mozilla.fenix.settings.toggle
@ -54,6 +57,16 @@ interface QuickSettingsController {
* feature [PhoneFeature] which the user granted Android permission(s) for.
*/
fun handleAndroidPermissionGranted(feature: PhoneFeature)
/**
* @see [TrackingProtectionInteractor.onTrackingProtectionToggled]
*/
fun handleTrackingProtectionToggled(isEnabled: Boolean)
/**
* @see [TrackingProtectionInteractor.onBlockedItemsClicked]
*/
fun handleBlockedItemsClicked()
}
/**
@ -155,6 +168,24 @@ class DefaultQuickSettingsController(
)
}
override fun handleTrackingProtectionToggled(isEnabled: Boolean) {
TODO("Not yet implemented")
}
override fun handleBlockedItemsClicked() {
dismiss.invoke()
val state = quickSettingsStore.state.trackingProtectionState
val directions = QuickSettingsSheetDialogFragmentDirections
.actionGlobalTrackingProtectionPanelDialogFragment(
sessionId = sessionId,
url = state.url,
trackingProtectionEnabled = state.isTrackingProtectionEnabled,
gravity = context.components.settings.toolbarPosition.androidGravity
)
navController.nav(R.id.quickSettingsSheetDialogFragment, directions)
}
/**
* Request a certain set of runtime Android permissions.
*

@ -15,6 +15,7 @@ import mozilla.components.feature.sitepermissions.SitePermissionsRules.AutoplayA
import mozilla.components.lib.state.State
import org.mozilla.fenix.R
import org.mozilla.fenix.settings.PhoneFeature
import org.mozilla.fenix.trackingprotection.TrackingProtectionState
import org.mozilla.fenix.utils.Settings
/**
@ -24,7 +25,8 @@ import org.mozilla.fenix.utils.Settings
*/
data class QuickSettingsFragmentState(
val webInfoState: WebsiteInfoState,
val websitePermissionsState: WebsitePermissionsState
val websitePermissionsState: WebsitePermissionsState,
val trackingProtectionState: TrackingProtectionState
) : State
/**

@ -6,16 +6,19 @@ package org.mozilla.fenix.settings.quicksettings
import android.content.Context
import androidx.annotation.VisibleForTesting
import mozilla.components.browser.state.selector.findTabOrCustomTab
import mozilla.components.browser.state.state.content.PermissionHighlightsState
import mozilla.components.concept.engine.permission.SitePermissions
import mozilla.components.lib.state.Action
import mozilla.components.lib.state.Reducer
import mozilla.components.lib.state.State
import mozilla.components.lib.state.Store
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.settings.PhoneFeature
import org.mozilla.fenix.settings.quicksettings.QuickSettingsFragmentStore.Companion.createStore
import org.mozilla.fenix.settings.quicksettings.ext.shouldBeEnabled
import org.mozilla.fenix.settings.quicksettings.ext.shouldBeVisible
import org.mozilla.fenix.trackingprotection.TrackingProtectionState
import org.mozilla.fenix.utils.Settings
import java.util.EnumMap
@ -48,7 +51,10 @@ class QuickSettingsFragmentStore(
* @param isSecured [Boolean] whether the connection is secured (TLS) or not.
* @param permissions [SitePermissions]? list of website permissions and their status.
* @param settings [Settings] application settings.
* @param certificateName [String] the certificate name of the current web page.
* @param certificateName [String] the certificate name of the current web page.
* @param sessionId [String] TODO
* @param isTrackingProtectionEnabled [Boolean] Current status of tracking protection
* for this session.
*/
@Suppress("LongParameterList")
fun createStore(
@ -59,7 +65,9 @@ class QuickSettingsFragmentStore(
isSecured: Boolean,
permissions: SitePermissions?,
permissionHighlights: PermissionHighlightsState,
settings: Settings
settings: Settings,
sessionId: String,
isTrackingProtectionEnabled: Boolean
) = QuickSettingsFragmentStore(
QuickSettingsFragmentState(
webInfoState = createWebsiteInfoState(
@ -73,6 +81,12 @@ class QuickSettingsFragmentStore(
permissions,
permissionHighlights,
settings
),
trackingProtectionState = createTrackingProtectionState(
context,
sessionId,
websiteUrl,
isTrackingProtectionEnabled
)
)
)
@ -127,6 +141,33 @@ class QuickSettingsFragmentStore(
return state
}
/**
* Construct an initial [TrackingProtectionState] to be rendered by
* [TrackingProtectionView].
*
* @param context [Context] used for various Android interactions.
* @param sessionId [String] TODO
* @param websiteUrl [String] the URL of the current web page.
* @param isTrackingProtectionEnabled [Boolean] Current status of tracking protection
* for this session.
*/
@VisibleForTesting
fun createTrackingProtectionState(
context: Context,
sessionId: String,
websiteUrl: String,
isTrackingProtectionEnabled: Boolean
): TrackingProtectionState {
return TrackingProtectionState(
tab = context.components.core.store.state.findTabOrCustomTab(sessionId),
url = websiteUrl,
isTrackingProtectionEnabled = isTrackingProtectionEnabled,
listTrackers = listOf(),
mode = TrackingProtectionState.Mode.Normal,
lastAccessedCategory = ""
)
}
/**
* [PhoneFeature] to a [WebsitePermission] mapper.
*/

@ -15,7 +15,7 @@ package org.mozilla.fenix.settings.quicksettings
*/
class QuickSettingsInteractor(
private val controller: QuickSettingsController
) : WebsitePermissionInteractor {
) : WebsitePermissionInteractor, TrackingProtectionInteractor {
override fun onPermissionsShown() {
controller.handlePermissionsShown()
}
@ -27,4 +27,12 @@ class QuickSettingsInteractor(
override fun onAutoplayChanged(value: AutoplayValue) {
controller.handleAutoplayChanged(value)
}
override fun onTrackingProtectionToggled(isEnabled: Boolean) {
controller.handleTrackingProtectionToggled(isEnabled)
}
override fun onBlockedItemsClicked() {
controller.handleBlockedItemsClicked()
}
}

@ -50,7 +50,9 @@ class QuickSettingsSheetDialogFragment : AppCompatDialogFragment() {
private lateinit var quickSettingsController: QuickSettingsController
private lateinit var websiteInfoView: WebsiteInfoView
private lateinit var websitePermissionsView: WebsitePermissionsView
private lateinit var trackingProtectionView: TrackingProtectionView
private lateinit var interactor: QuickSettingsInteractor
private var tryToRequestPermissions: Boolean = false
private val args by navArgs<QuickSettingsSheetDialogFragmentArgs>()
@ -77,7 +79,9 @@ class QuickSettingsSheetDialogFragment : AppCompatDialogFragment() {
permissions = args.sitePermissions,
settings = components.settings,
certificateName = args.certificateName,
permissionHighlights = args.permissionHighlights
permissionHighlights = args.permissionHighlights,
sessionId = args.sessionId,
isTrackingProtectionEnabled = args.isTrackingProtectionEnabled
)
quickSettingsController = DefaultQuickSettingsController(
@ -105,6 +109,8 @@ class QuickSettingsSheetDialogFragment : AppCompatDialogFragment() {
websiteInfoView = WebsiteInfoView(binding.websiteInfoLayout)
websitePermissionsView =
WebsitePermissionsView(binding.websitePermissionsLayout, interactor)
trackingProtectionView =
TrackingProtectionView(rootView.trackingProtectionLayout, interactor)
return rootView
}
@ -143,6 +149,7 @@ class QuickSettingsSheetDialogFragment : AppCompatDialogFragment() {
consumeFrom(quickSettingsStore) {
websiteInfoView.update(it.webInfoState)
websitePermissionsView.update(it.websitePermissionsState)
trackingProtectionView.update(it.trackingProtectionState)
}
}

@ -0,0 +1,67 @@
/* 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
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import kotlinx.android.extensions.LayoutContainer
import kotlinx.android.synthetic.main.component_tracking_protection_panel.trackingProtectionSwitch
import kotlinx.android.synthetic.main.quicksettings_tracking_protection.*
import kotlinx.android.synthetic.main.switch_with_description.view.*
import org.mozilla.fenix.R
import org.mozilla.fenix.trackingprotection.TrackingProtectionState
/**
* Contract declaring all possible user interactions with [TrackingProtectionView]
*/
interface TrackingProtectionInteractor {
/**
* Called whenever the tracking protection toggle for this site is toggled
*
* @param isEnabled new status of session tracking protection
*/
fun onTrackingProtectionToggled(isEnabled: Boolean)
/**
* Navigates to the tracking protection preferences. Called when a user clicks on the
* "Blocked items" button.
*/
fun onBlockedItemsClicked()
}
/**
* TODO
*
* @param containerView [ViewGroup] in which this View will inflate itself.
* @param interactor [TrackingProtectionInteractor] which will have delegated to all user interactions.
*/
class TrackingProtectionView(
override val containerView: ViewGroup,
val interactor: TrackingProtectionInteractor
) : LayoutContainer {
private val context = containerView.context
val view: View = LayoutInflater.from(context)
.inflate(R.layout.quicksettings_tracking_protection, containerView, true)
fun update(state: TrackingProtectionState) {
bindTrackingProtectionInfo(state.isTrackingProtectionEnabled)
trackingProtectionBlockedItems.setOnClickListener {
interactor.onBlockedItemsClicked()
}
}
private fun bindTrackingProtectionInfo(isTrackingProtectionEnabled: Boolean) {
trackingProtectionSwitch.switch_widget.isChecked = isTrackingProtectionEnabled
trackingProtectionSwitch.switch_widget.jumpDrawablesToCurrentState()
trackingProtectionSwitch.switch_widget.setOnCheckedChangeListener { _, isChecked ->
interactor.onTrackingProtectionToggled(isChecked)
}
}
}

@ -35,26 +35,13 @@ class WebsiteInfoView(
*/
fun update(state: WebsiteInfoState) {
bindUrl(state.websiteUrl)
bindTitle(state.websiteTitle)
bindSecurityInfo(state.websiteSecurityUiValues)
bindCertificateName(state.certificateName)
}
private fun bindUrl(websiteUrl: String) {
binding.url.text = websiteUrl
}
private fun bindTitle(websiteTitle: String) {
binding.title.text = websiteTitle
}
private fun bindCertificateName(cert: String) {
val certificateLabel =
binding.root.context.getString(R.string.certificate_info_verified_by, cert)
binding.certificateInfo.text = certificateLabel
binding.certificateInfo.isVisible = cert.isNotEmpty()
}
private fun bindSecurityInfo(uiValues: WebsiteSecurityUiValues) {
val tint = getColor(binding.root.context, uiValues.iconTintRes)
binding.securityInfo.setText(uiValues.securityInfoRes)

@ -148,7 +148,7 @@ class TrackingProtectionOverlay(
val toolbar = getToolbar()
val trackingProtectionIcon: View =
toolbar.findViewById(R.id.mozac_browser_toolbar_tracking_protection_indicator)
toolbar.findViewById(R.id.mozac_browser_toolbar_security_indicator)
val xOffset = triangleMarginStartPx + triangleWidthPx / 2
@ -172,12 +172,10 @@ class TrackingProtectionOverlay(
it.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
}
val etpShield =
getToolbar().findViewById<View>(R.id.mozac_browser_toolbar_tracking_protection_indicator)
trackingOnboardingDialog.message.setOnClickListener {
metrics.track(Event.ContextualHintETPInsideTap)
trackingOnboardingDialog.dismiss()
etpShield.performClick()
trackingProtectionIcon.performClick()
}
metrics.track(Event.ContextualHintETPDisplayed)

@ -87,9 +87,9 @@ class TrackingProtectionPanelDialogFragment : AppCompatDialogFragment(), UserInt
trackingProtectionStore = StoreProvider.get(this) {
TrackingProtectionStore(
TrackingProtectionState(
tab,
args.url,
args.trackingProtectionEnabled,
tab = tab,
url = args.url,
isTrackingProtectionEnabled = args.trackingProtectionEnabled,
listTrackers = listOf(),
mode = TrackingProtectionState.Mode.Normal,
lastAccessedCategory = ""

@ -47,12 +47,14 @@ sealed class TrackingProtectionAction : Action {
/**
* The state for the Tracking Protection Panel
* @property tab TODO
* @property url Current URL to display
* @property isTrackingProtectionEnabled Current status of tracking protection for this session (ie is an exception)
* @property isTrackingProtectionEnabled Current status of tracking protection for this session
* (ie is an exception)
* @property listTrackers Current Tracker Log list of blocked and loaded tracker categories
* @property mode Current Mode of TrackingProtection
* @property lastAccessedCategory Remembers the last accessed details category, used to move
* accessibly focus after returning from details_moode
* accessibly focus after returning from details_mode
*/
data class TrackingProtectionState(
val tab: SessionState?,

@ -26,7 +26,7 @@
android:id="@+id/websitePermissionsLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent" />
app:layout_constraintBottom_toTopOf="@id/trackingProtectionDivider" />
<View
android:id="@+id/webSitePermissionsDivider"
@ -37,6 +37,21 @@
android:background="?neutralFaded"
app:layout_constraintBottom_toTopOf="@id/websitePermissionsLayout" />
<FrameLayout
android:id="@+id/trackingProtectionLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent" />
<View
android:id="@+id/trackingProtectionDivider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:background="?neutralFaded"
app:layout_constraintBottom_toTopOf="@id/trackingProtectionLayout" />
<androidx.constraintlayout.widget.Group
android:id="@+id/websitePermissionsGroup"
android:layout_width="wrap_content"

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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/. -->
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<org.mozilla.fenix.trackingprotection.SwitchWithDescription
android:id="@+id/trackingProtectionSwitch"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="@dimen/tracking_protection_item_height"
android:text="@string/preference_enhanced_tracking_protection"
app:layout_constraintBottom_toTopOf="@id/trackingProtectionBlockedItems"
app:layout_constraintTop_toTopOf="parent"
app:switchDescription="@string/etp_panel_on"
app:switchIcon="@drawable/ic_tracking_protection"
app:switchTitle="@string/preference_enhanced_tracking_protection" />
<!-- TODO: Match drawablePadding with Design Spec. Using @style/QuickSettingsText.Icon as a placeholder -->
<!-- TODO: Match layout_height with Design Spec. Using @dimen/quicksettings_item_height as a placeholder -->
<TextView
android:id="@+id/trackingProtectionBlockedItems"
style="@style/QuickSettingsText.Icon"
android:layout_width="0dp"
android:layout_height="@dimen/quicksettings_item_height"
android:gravity="end|center_vertical"
android:layout_alignParentEnd="true"
android:text="@string/preference_enhanced_tracking_protection_blocked_items"
app:drawableEndCompat="@drawable/ic_arrowhead_right"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

@ -16,16 +16,9 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:minHeight="@dimen/tracking_protection_item_height">
<TextView
android:id="@+id/title"
style="@style/QuickSettingsText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="8dp"
android:textStyle="bold"
tools:text="Wikipedia" />
android:minHeight="@dimen/tracking_protection_item_height"
android:paddingTop="8dp"
android:paddingBottom="8dp">
<TextView
android:id="@+id/url"
@ -61,19 +54,7 @@
android:layout_width="match_parent"
android:paddingStart="0dp"
android:layout_height="wrap_content"
tools:text="Secure connection" />
<TextView
android:id="@+id/certificateInfo"
style="@style/QuickSettingsSmallText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:paddingTop="0dp"
android:paddingBottom="2dp"
tools:text="Verified By: E-Corp" />
tools:text="Connection is secure" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

@ -780,6 +780,9 @@
<argument
android:name="permissionHighlights"
app:argType="mozilla.components.browser.state.state.content.PermissionHighlightsState" />
<argument
android:name="isTrackingProtectionEnabled"
app:argType="boolean" />
</dialog>
<fragment
android:id="@+id/accountProblemFragment"

@ -1370,6 +1370,9 @@
<string name="preference_enhanced_tracking_protection_custom_cryptominers">Cryptominers</string>
<!-- Preference for enhanced tracking protection for the custom protection settings -->
<string name="preference_enhanced_tracking_protection_custom_fingerprinters">Fingerprinters</string>
<!-- TODO -->
<string name="preference_enhanced_tracking_protection_blocked_items">Blocked items</string>
<!-- Header for categories that are being being blocked by current Enhanced Tracking Protection settings -->
<string name="enhanced_tracking_protection_blocked">Blocked</string>
<!-- Header for categories that are being not being blocked by current Enhanced Tracking Protection settings -->
<string name="enhanced_tracking_protection_allowed">Allowed</string>

Loading…
Cancel
Save