diff --git a/app/src/main/java/org/mozilla/fenix/settings/TrackingProtectionFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/TrackingProtectionFragment.kt index 244a6192b..0349c69d8 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/TrackingProtectionFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/TrackingProtectionFragment.kt @@ -17,10 +17,11 @@ import org.mozilla.fenix.R import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.getPreferenceKey -import org.mozilla.fenix.ext.metrics import org.mozilla.fenix.ext.nav +import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.showToolbar +import org.mozilla.fenix.trackingprotection.TrackingProtectionMode /** * Displays the toggle for tracking protection, options for tracking protection policy and a button @@ -34,9 +35,6 @@ class TrackingProtectionFragment : PreferenceFragmentCompat() { requireView().findNavController().navigate(directions) true } - private lateinit var radioStrict: RadioButtonInfoPreference - private lateinit var radioStandard: RadioButtonInfoPreference - private lateinit var radioCustom: RadioButtonInfoPreference private lateinit var customCookies: CheckBoxPreference private lateinit var customCookiesSelect: DropDownPreference private lateinit var customTracking: CheckBoxPreference @@ -46,10 +44,10 @@ class TrackingProtectionFragment : PreferenceFragmentCompat() { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.tracking_protection_preferences, rootKey) - bindStrict() - bindStandard() - bindCustom() - setupRadioGroups() + val radioStrict = bindTrackingProtectionRadio(TrackingProtectionMode.STRICT) + val radioStandard = bindTrackingProtectionRadio(TrackingProtectionMode.STANDARD) + val radioCustom = bindCustom() + setupRadioGroups(radioStrict, radioStandard, radioCustom) updateCustomOptionsVisibility() } @@ -96,79 +94,42 @@ class TrackingProtectionFragment : PreferenceFragmentCompat() { preferenceExceptions?.onPreferenceClickListener = exceptionsClickListener } - private fun bindStrict() { - val keyStrict = getString(R.string.pref_key_tracking_protection_strict_default) - radioStrict = requireNotNull(findPreference(keyStrict)) - radioStrict.contentDescription = - getString(R.string.preference_enhanced_tracking_protection_strict_info_button) + private fun bindTrackingProtectionRadio( + mode: TrackingProtectionMode + ): RadioButtonInfoPreference { + val radio = requireNotNull(findPreference( + getPreferenceKey(mode.preferenceKey) + )) + radio.contentDescription = getString(mode.contentDescriptionRes) - radioStrict.onClickListener { + val metrics = requireComponents.analytics.metrics + radio.onClickListener { updateCustomOptionsVisibility() updateTrackingProtectionPolicy() - context?.metrics?.track( - Event.TrackingProtectionSettingChanged( - Event.TrackingProtectionSettingChanged.Setting.STRICT - ) - ) - } - - radioStrict.onInfoClickListener { - nav( - R.id.trackingProtectionFragment, - TrackingProtectionFragmentDirections - .actionTrackingProtectionFragmentToTrackingProtectionBlockingFragment( - getString(R.string.preference_enhanced_tracking_protection_strict_default) - ) - ) - } - } - - private fun bindStandard() { - val keyStandard = getString(R.string.pref_key_tracking_protection_standard_option) - radioStandard = requireNotNull(findPreference(keyStandard)) - radioStandard.contentDescription = - getString(R.string.preference_enhanced_tracking_protection_standard_info_button) - - radioStandard.onClickListener { - updateCustomOptionsVisibility() - updateTrackingProtectionPolicy() - context?.metrics?.track( - Event.TrackingProtectionSettingChanged( + when (mode) { + TrackingProtectionMode.STANDARD -> Event.TrackingProtectionSettingChanged.Setting.STANDARD - ) - ) + TrackingProtectionMode.STRICT -> + Event.TrackingProtectionSettingChanged.Setting.STRICT + TrackingProtectionMode.CUSTOM -> null + }?.let { setting -> + metrics.track(Event.TrackingProtectionSettingChanged(setting)) + } } - radioStandard.onInfoClickListener { + radio.onInfoClickListener { nav( R.id.trackingProtectionFragment, TrackingProtectionFragmentDirections - .actionTrackingProtectionFragmentToTrackingProtectionBlockingFragment( - getString(R.string.preference_enhanced_tracking_protection_standard_option) - ) + .actionTrackingProtectionFragmentToTrackingProtectionBlockingFragment(mode) ) } + + return radio } - private fun bindCustom() { - val keyCustom = getString(R.string.pref_key_tracking_protection_custom_option) - radioCustom = requireNotNull(findPreference(keyCustom)) - radioCustom.contentDescription = - getString(R.string.preference_enhanced_tracking_protection_custom_info_button) - - radioCustom.onClickListener { - updateCustomOptionsVisibility() - updateTrackingProtectionPolicy() - } - radioCustom.onInfoClickListener { - nav( - R.id.trackingProtectionFragment, - TrackingProtectionFragmentDirections - .actionTrackingProtectionFragmentToTrackingProtectionBlockingFragment( - getString(R.string.preference_enhanced_tracking_protection_custom) - ) - ) - } + private fun bindCustom(): RadioButtonInfoPreference { + val radio = bindTrackingProtectionRadio(TrackingProtectionMode.CUSTOM) customCookies = requireNotNull( findPreference( @@ -254,6 +215,8 @@ class TrackingProtectionFragment : PreferenceFragmentCompat() { } updateCustomOptionsVisibility() + + return radio } private fun updateTrackingProtectionPolicy() { @@ -265,7 +228,11 @@ class TrackingProtectionFragment : PreferenceFragmentCompat() { } } - private fun setupRadioGroups() { + private fun setupRadioGroups( + radioStrict: RadioButtonInfoPreference, + radioStandard: RadioButtonInfoPreference, + radioCustom: RadioButtonInfoPreference + ) { radioStandard.addToRadioGroup(radioStrict) radioStrict.addToRadioGroup(radioStandard) diff --git a/app/src/main/java/org/mozilla/fenix/trackingprotection/SwitchWithDescription.kt b/app/src/main/java/org/mozilla/fenix/trackingprotection/SwitchWithDescription.kt index 2f5c17164..930fe5d1b 100644 --- a/app/src/main/java/org/mozilla/fenix/trackingprotection/SwitchWithDescription.kt +++ b/app/src/main/java/org/mozilla/fenix/trackingprotection/SwitchWithDescription.kt @@ -29,10 +29,7 @@ class SwitchWithDescription @JvmOverloads constructor( R.drawable.ic_tracking_protection ) switch_widget.putCompoundDrawablesRelativeWithIntrinsicBounds( - start = AppCompatResources.getDrawable( - context, - id - ) + start = AppCompatResources.getDrawable(context, id) ) trackingProtectionCategoryTitle.text = resources.getString( getResourceId( diff --git a/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackerBuckets.kt b/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackerBuckets.kt index 7cc52ec42..aaf11831a 100644 --- a/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackerBuckets.kt +++ b/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackerBuckets.kt @@ -53,7 +53,7 @@ class TrackerBuckets { /** * Gets the tracker URLs for a given category. */ - operator fun get(key: TrackingProtectionCategory, blocked: Boolean) = + fun get(key: TrackingProtectionCategory, blocked: Boolean) = if (blocked) buckets.blockedBucketMap[key].orEmpty() else buckets.loadedBucketMap[key].orEmpty() companion object { diff --git a/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackingProtectionBlockingFragment.kt b/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackingProtectionBlockingFragment.kt index c6143d00f..0bacaebfd 100644 --- a/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackingProtectionBlockingFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackingProtectionBlockingFragment.kt @@ -18,42 +18,33 @@ class TrackingProtectionBlockingFragment : Fragment(R.layout.fragment_tracking_protection_blocking) { private val args: TrackingProtectionBlockingFragmentArgs by navArgs() - private var isCustomProtection: Boolean = false - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - isCustomProtection = requireContext().settings().useCustomTrackingProtection - } + private val settings by lazy { requireContext().settings() } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) when (args.protectionMode) { - - getString(R.string.preference_enhanced_tracking_protection_standard_option) -> { + TrackingProtectionMode.STANDARD -> { category_tracking_content.isVisible = false } - getString(R.string.preference_enhanced_tracking_protection_strict) -> return + TrackingProtectionMode.STRICT -> {} - getString(R.string.preference_enhanced_tracking_protection_custom) -> { + TrackingProtectionMode.CUSTOM -> { category_fingerprinters.isVisible = - requireContext().settings().blockFingerprintersInCustomTrackingProtection + settings.blockFingerprintersInCustomTrackingProtection category_cryptominers.isVisible = - requireContext().settings().blockCryptominersInCustomTrackingProtection + settings.blockCryptominersInCustomTrackingProtection category_cookies.isVisible = - requireContext().settings().blockCookiesInCustomTrackingProtection + settings.blockCookiesInCustomTrackingProtection category_tracking_content.isVisible = - requireContext().settings().blockTrackingContentInCustomTrackingProtection + settings.blockTrackingContentInCustomTrackingProtection } - - else -> return } } override fun onResume() { super.onResume() - showToolbar(args.protectionMode) + showToolbar(getString(args.protectionMode.titleRes)) } } diff --git a/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackingProtectionCategoryItem.kt b/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackingProtectionCategoryItem.kt index 1f42a5a6c..15d4a52bb 100644 --- a/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackingProtectionCategoryItem.kt +++ b/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackingProtectionCategoryItem.kt @@ -7,6 +7,7 @@ package org.mozilla.fenix.trackingprotection import android.content.Context import android.util.AttributeSet import android.view.LayoutInflater +import androidx.appcompat.content.res.AppCompatResources import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.content.withStyledAttributes import kotlinx.android.synthetic.main.tracking_protection_category.view.* @@ -30,7 +31,7 @@ class TrackingProtectionCategoryItem @JvmOverloads constructor( R.styleable.TrackingProtectionCategory_categoryItemIcon, R.drawable.ic_cryptominers ) - trackingProtectionCategoryIcon?.background = resources.getDrawable(id, context.theme) + trackingProtectionCategoryIcon?.background = AppCompatResources.getDrawable(context, id) trackingProtectionCategoryTitle?.text = resources.getString( getResourceId( R.styleable.TrackingProtectionCategory_categoryItemTitle, diff --git a/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackingProtectionMode.kt b/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackingProtectionMode.kt new file mode 100644 index 000000000..380b431b1 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackingProtectionMode.kt @@ -0,0 +1,34 @@ +/* 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.trackingprotection + +import android.os.Parcelable +import androidx.annotation.StringRes +import kotlinx.android.parcel.Parcelize +import org.mozilla.fenix.R + +@Parcelize +enum class TrackingProtectionMode( + @StringRes val preferenceKey: Int, + @StringRes val titleRes: Int, + @StringRes val contentDescriptionRes: Int +) : Parcelable { + + STANDARD( + preferenceKey = R.string.pref_key_tracking_protection_standard_option, + titleRes = R.string.preference_enhanced_tracking_protection_standard_option, + contentDescriptionRes = R.string.preference_enhanced_tracking_protection_standard_info_button + ), + STRICT( + preferenceKey = R.string.pref_key_tracking_protection_strict_default, + titleRes = R.string.preference_enhanced_tracking_protection_strict, + contentDescriptionRes = R.string.preference_enhanced_tracking_protection_strict_info_button + ), + CUSTOM( + preferenceKey = R.string.pref_key_tracking_protection_custom_option, + titleRes = R.string.preference_enhanced_tracking_protection_custom, + contentDescriptionRes = R.string.preference_enhanced_tracking_protection_custom_info_button + ) +} diff --git a/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackingProtectionPanelDialogFragment.kt b/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackingProtectionPanelDialogFragment.kt index f42604992..570ed2ec9 100644 --- a/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackingProtectionPanelDialogFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackingProtectionPanelDialogFragment.kt @@ -57,6 +57,16 @@ class TrackingProtectionPanelDialogFragment : AppCompatDialogFragment(), UserInt private lateinit var trackingProtectionStore: TrackingProtectionStore private lateinit var trackingProtectionView: TrackingProtectionPanelView private lateinit var trackingProtectionInteractor: TrackingProtectionPanelInteractor + private lateinit var trackingProtectionUseCases: TrackingProtectionUseCases + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val components = requireComponents + trackingProtectionUseCases = TrackingProtectionUseCases( + sessionManager = components.core.sessionManager, + engine = components.core.engine + ) + } override fun onCreateView( inflater: LayoutInflater, @@ -85,47 +95,34 @@ class TrackingProtectionPanelDialogFragment : AppCompatDialogFragment(), UserInt ) trackingProtectionView = TrackingProtectionPanelView(view.fragment_tp, trackingProtectionInteractor) - updateTrackers() + session?.let { updateTrackers(it) } return view } private val sessionObserver = object : Session.Observer { override fun onUrlChanged(session: Session, url: String) { - trackingProtectionStore.dispatch( - TrackingProtectionAction.UrlChange(url) - ) + trackingProtectionStore.dispatch(TrackingProtectionAction.UrlChange(url)) } override fun onTrackerBlocked(session: Session, tracker: Tracker, all: List) { - updateTrackers() + updateTrackers(session) } override fun onTrackerLoaded(session: Session, tracker: Tracker, all: List) { - updateTrackers() + updateTrackers(session) } } - private fun updateTrackers() { - context?.let { context -> - val session = - context.components.core.sessionManager.findSessionById(args.sessionId) ?: return - val useCase = TrackingProtectionUseCases( - sessionManager = context.components.core.sessionManager, - engine = context.components.core.engine - ) - - useCase.fetchTrackingLogs( - session, - onSuccess = { - trackingProtectionStore.dispatch( - TrackingProtectionAction.TrackerLogChange(it) - ) - }, - onError = { - Logger.error("TrackingProtectionUseCases - fetchTrackingLogs onError", it) - } - ) - } + private fun updateTrackers(session: Session) { + trackingProtectionUseCases.fetchTrackingLogs( + session, + onSuccess = { + trackingProtectionStore.dispatch(TrackingProtectionAction.TrackerLogChange(it)) + }, + onError = { + Logger.error("TrackingProtectionUseCases - fetchTrackingLogs onError", it) + } + ) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { @@ -150,17 +147,13 @@ class TrackingProtectionPanelDialogFragment : AppCompatDialogFragment(), UserInt private fun toggleTrackingProtection(isEnabled: Boolean) { context?.let { context -> - val useCase = TrackingProtectionUseCases( - sessionManager = context.components.core.sessionManager, - engine = context.components.core.engine - ) val session = context.components.core.sessionManager.findSessionById(args.sessionId) session?.let { if (isEnabled) { - useCase.removeException(it) + trackingProtectionUseCases.removeException(it) } else { context.metrics.track(Event.TrackingProtectionException) - useCase.addException(it) + trackingProtectionUseCases.addException(it) } with(context.components) { diff --git a/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackingProtectionPanelView.kt b/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackingProtectionPanelView.kt index cd79060be..79e42c13a 100644 --- a/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackingProtectionPanelView.kt +++ b/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackingProtectionPanelView.kt @@ -77,11 +77,18 @@ class TrackingProtectionPanelView( private var shouldFocusAccessibilityView: Boolean = true - fun update(state: TrackingProtectionState) { - if (state.mode != mode) { - mode = state.mode + init { + protection_settings.setOnClickListener { + interactor.selectTrackingProtectionSettings() } + details_back.setOnClickListener { + interactor.onBackPressed() + } + setCategoryClickListeners() + } + fun update(state: TrackingProtectionState) { + mode = state.mode bucketedTrackers.updateIfNeeded(state.listTrackers) when (val mode = state.mode) { @@ -103,16 +110,31 @@ class TrackingProtectionPanelView( not_blocking_header.isGone = bucketedTrackers.loadedIsEmpty() bindUrl(state.url) bindTrackingProtectionInfo(state.isTrackingProtectionEnabled) - protection_settings.setOnClickListener { - interactor.selectTrackingProtectionSettings() - } blocking_header.isGone = bucketedTrackers.blockedIsEmpty() updateCategoryVisibility() - setCategoryClickListeners() focusAccessibilityLastUsedCategory(state.lastAccessedCategory) } + private fun setUIForDetailsMode( + category: TrackingProtectionCategory, + categoryBlocked: Boolean + ) { + normal_mode.visibility = View.GONE + details_mode.visibility = View.VISIBLE + category_title.setText(category.title) + blocking_text_list.text = bucketedTrackers.get(category, categoryBlocked).joinToString("\n") + category_description.setText(category.description) + details_blocking_header.setText(if (categoryBlocked) { + R.string.enhanced_tracking_protection_blocked + } else { + R.string.enhanced_tracking_protection_allowed + }) + + details_back.requestFocus() + details_back.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED) + } + /** * Will force accessibility focus to last entered details category. * Called when user returns from details_mode. @@ -180,32 +202,6 @@ class TrackingProtectionPanelView( interactor.openDetails(category, categoryBlocked = !isLoaded(v)) } - private fun setUIForDetailsMode( - category: TrackingProtectionCategory, - categoryBlocked: Boolean - ) { - val context = view.context - - normal_mode.visibility = View.GONE - details_mode.visibility = View.VISIBLE - category_title.text = context.getString(category.title) - blocking_text_list.text = bucketedTrackers.get(category, categoryBlocked).joinToString("\n") - category_description.text = context.getString(category.description) - details_blocking_header.text = context.getString( - if (categoryBlocked) { - R.string.enhanced_tracking_protection_blocked - } else { - R.string.enhanced_tracking_protection_allowed - } - ) - details_back.setOnClickListener { - interactor.onBackPressed() - } - - details_back.requestFocus() - details_back.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED) - } - private fun bindUrl(url: String) { this.url.text = url.toUri().hostWithoutCommonPrefixes } @@ -239,9 +235,9 @@ class TrackingProtectionPanelView( ViewCompat.setAccessibilityDelegate(view2, object : AccessibilityDelegateCompat() { override fun onInitializeAccessibilityNodeInfo( host: View?, - info: AccessibilityNodeInfoCompat? + info: AccessibilityNodeInfoCompat ) { - info?.setTraversalAfter(view1) + info.setTraversalAfter(view1) super.onInitializeAccessibilityNodeInfo(host, info) } }) diff --git a/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackingProtectionStore.kt b/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackingProtectionStore.kt index 49f326bad..a9d79fd18 100644 --- a/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackingProtectionStore.kt +++ b/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackingProtectionStore.kt @@ -4,6 +4,7 @@ package org.mozilla.fenix.trackingprotection +import androidx.annotation.StringRes import mozilla.components.browser.session.Session import mozilla.components.concept.engine.content.blocking.TrackerLog import mozilla.components.lib.state.Action @@ -73,7 +74,10 @@ data class TrackingProtectionState( /** * The 5 categories of Tracking Protection to display */ -enum class TrackingProtectionCategory(val title: Int, val description: Int) { +enum class TrackingProtectionCategory( + @StringRes val title: Int, + @StringRes val description: Int +) { SOCIAL_MEDIA_TRACKERS( R.string.etp_social_media_trackers_title, R.string.etp_social_media_trackers_description diff --git a/app/src/main/res/layout/component_tracking_protection_panel.xml b/app/src/main/res/layout/component_tracking_protection_panel.xml index 53adf0e5b..27383a466 100644 --- a/app/src/main/res/layout/component_tracking_protection_panel.xml +++ b/app/src/main/res/layout/component_tracking_protection_panel.xml @@ -188,7 +188,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="20dp" - android:tint="?attr/primaryText" + app:tint="?attr/primaryText" android:contentDescription="@string/etp_back_button_content_description" app:layout_constraintBottom_toBottomOf="@+id/category_description" app:layout_constraintStart_toStartOf="parent" diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index 915bc29ce..fbd4ac379 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -696,10 +696,11 @@ + android:name="org.mozilla.fenix.trackingprotection.TrackingProtectionBlockingFragment" + tools:layout="@layout/fragment_tracking_protection_blocking"> + app:argType="org.mozilla.fenix.trackingprotection.TrackingProtectionMode" />