Skip to content

Commit

Permalink
For mozilla-mobile#18629: add support for SmartBlock exceptions
Browse files Browse the repository at this point in the history
  • Loading branch information
Amejia481 authored and mergify[bot] committed Sep 13, 2021
1 parent eba5005 commit cbb8f80
Show file tree
Hide file tree
Showing 11 changed files with 160 additions and 59 deletions.
1 change: 1 addition & 0 deletions app/src/main/java/org/mozilla/fenix/BrowserDirection.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ enum class BrowserDirection(@IdRes val fragmentId: Int) {
FromTrackingProtectionExceptions(R.id.trackingProtectionExceptionsFragment),
FromAbout(R.id.aboutFragment),
FromTrackingProtection(R.id.trackingProtectionFragment),
FromTrackingProtectionDialog(R.id.trackingProtectionPanelDialogFragment),
FromSavedLoginsFragment(R.id.savedLoginsFragment),
FromAddNewDeviceFragment(R.id.addNewDeviceFragment),
FromAddSearchEngineFragment(R.id.addSearchEngineFragment),
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/java/org/mozilla/fenix/HomeActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ import org.mozilla.fenix.tabstray.TabsTrayFragment
import org.mozilla.fenix.tabstray.TabsTrayFragmentDirections
import org.mozilla.fenix.theme.DefaultThemeManager
import org.mozilla.fenix.theme.ThemeManager
import org.mozilla.fenix.trackingprotection.TrackingProtectionPanelDialogFragmentDirections
import org.mozilla.fenix.utils.BrowsersCache
import org.mozilla.fenix.utils.Settings
import java.lang.ref.WeakReference
Expand Down Expand Up @@ -746,6 +747,8 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
AboutFragmentDirections.actionGlobalBrowser(customTabSessionId)
BrowserDirection.FromTrackingProtection ->
TrackingProtectionFragmentDirections.actionGlobalBrowser(customTabSessionId)
BrowserDirection.FromTrackingProtectionDialog ->
TrackingProtectionPanelDialogFragmentDirections.actionGlobalBrowser(customTabSessionId)
BrowserDirection.FromSavedLoginsFragment ->
SavedLoginsAuthFragmentDirections.actionGlobalBrowser(customTabSessionId)
BrowserDirection.FromAddNewDeviceFragment ->
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/java/org/mozilla/fenix/settings/SupportUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ object SupportUtils {
SEARCH_SUGGESTION("how-search-firefox-preview"),
CUSTOM_SEARCH_ENGINES("custom-search-engines"),
SYNC_SETUP("how-set-firefox-sync-firefox-android"),
QR_CAMERA_ACCESS("qr-camera-access")
QR_CAMERA_ACCESS("qr-camera-access"),
SMARTBLOCK("smartblock-enhanced-tracking-protection")
}

enum class MozillaPage(internal val path: String) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@ package org.mozilla.fenix.trackingprotection
import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy.TrackingCategory
import mozilla.components.concept.engine.content.blocking.Tracker
import mozilla.components.concept.engine.content.blocking.TrackerLog
import mozilla.components.support.ktx.kotlin.tryGetHostFromUrl
import org.mozilla.fenix.trackingprotection.TrackingProtectionCategory.CROSS_SITE_TRACKING_COOKIES
import org.mozilla.fenix.trackingprotection.TrackingProtectionCategory.CRYPTOMINERS
import org.mozilla.fenix.trackingprotection.TrackingProtectionCategory.FINGERPRINTERS
import org.mozilla.fenix.trackingprotection.TrackingProtectionCategory.SOCIAL_MEDIA_TRACKERS
import org.mozilla.fenix.trackingprotection.TrackingProtectionCategory.TRACKING_CONTENT
import java.util.EnumMap

typealias BucketMap = Map<TrackingProtectionCategory, List<String>>
typealias BucketMap = Map<TrackingProtectionCategory, List<TrackerLog>>

/**
* Sorts [Tracker]s into different buckets and exposes them as a map.
Expand Down Expand Up @@ -85,14 +84,14 @@ class TrackerBuckets {
* Create an empty mutable map of [TrackingProtectionCategory] to hostnames.
*/
private fun createMap() =
EnumMap<TrackingProtectionCategory, MutableList<String>>(TrackingProtectionCategory::class.java)
EnumMap<TrackingProtectionCategory, MutableList<TrackerLog>>(TrackingProtectionCategory::class.java)

/**
* Add the hostname of the [TrackerLog.url] into the map for the given category
* from Android Components. The category is transformed into a corresponding Fenix bucket,
* and the item is discarded if the category doesn't have a match.
*/
private fun MutableMap<TrackingProtectionCategory, MutableList<String>>.addTrackerHost(
private fun MutableMap<TrackingProtectionCategory, MutableList<TrackerLog>>.addTrackerHost(
category: TrackingCategory,
tracker: TrackerLog
) {
Expand All @@ -107,13 +106,13 @@ class TrackerBuckets {
}

/**
* Add the hostname of the [TrackerLog.url] into the map for the given [TrackingProtectionCategory].
* Add the hostname of the [TrackerLog] into the map for the given [TrackingProtectionCategory].
*/
private fun MutableMap<TrackingProtectionCategory, MutableList<String>>.addTrackerHost(
private fun MutableMap<TrackingProtectionCategory, MutableList<TrackerLog>>.addTrackerHost(
key: TrackingProtectionCategory,
tracker: TrackerLog
) {
getOrPut(key) { mutableListOf() }.add(tracker.url.tryGetHostFromUrl())
getOrPut(key) { mutableListOf() }.add(tracker)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import mozilla.components.support.base.feature.UserInteractionHandler
import mozilla.components.support.base.log.logger.Logger
import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifAnyChanged
import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifChanged
import org.mozilla.fenix.BrowserDirection
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.components.StoreProvider
Expand All @@ -45,6 +46,7 @@ import org.mozilla.fenix.databinding.FragmentTrackingProtectionBinding
import org.mozilla.fenix.ext.metrics
import org.mozilla.fenix.ext.nav
import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.settings.SupportUtils

@ExperimentalCoroutinesApi
@Suppress("TooManyFunctions")
Expand Down Expand Up @@ -102,6 +104,7 @@ class TrackingProtectionPanelDialogFragment : AppCompatDialogFragment(), UserInt
store = trackingProtectionStore,
navController = { findNavController() },
openTrackingProtectionSettings = ::openTrackingProtectionSettings,
openLearnMoreLink = ::handleLearnMoreClicked,
sitePermissions = args.sitePermissions,
gravity = args.gravity,
getCurrentTab = ::getCurrentTab
Expand Down Expand Up @@ -149,6 +152,16 @@ class TrackingProtectionPanelDialogFragment : AppCompatDialogFragment(), UserInt
)
}

private fun handleLearnMoreClicked() {
(activity as HomeActivity).openToBrowserAndLoad(
searchTermOrURL = SupportUtils.getGenericSumoURLForTopic(
SupportUtils.SumoTopic.SMARTBLOCK
),
newTab = true,
from = BrowserDirection.FromTrackingProtectionDialog
)
}

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return if (args.gravity == Gravity.BOTTOM) {
object : BottomSheetDialog(requireContext(), this.theme) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class TrackingProtectionPanelInteractor(
private val store: TrackingProtectionStore,
private val navController: () -> NavController,
private val openTrackingProtectionSettings: () -> Unit,
private val openLearnMoreLink: () -> Unit,
internal var sitePermissions: SitePermissions?,
private val gravity: Int,
private val getCurrentTab: () -> SessionState?
Expand All @@ -33,6 +34,10 @@ class TrackingProtectionPanelInteractor(
store.dispatch(TrackingProtectionAction.EnterDetailsMode(category, categoryBlocked))
}

override fun onLearnMoreClicked() {
openLearnMoreLink()
}

override fun selectTrackingProtectionSettings() {
openTrackingProtectionSettings.invoke()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,26 @@

package org.mozilla.fenix.trackingprotection

import android.text.method.LinkMovementMethod
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.accessibility.AccessibilityEvent
import androidx.annotation.VisibleForTesting
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.text.HtmlCompat
import androidx.core.view.AccessibilityDelegateCompat
import androidx.core.view.ViewCompat
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat
import androidx.core.view.isGone
import androidx.core.view.isVisible
import mozilla.components.browser.state.state.CustomTabSessionState
import mozilla.components.concept.engine.content.blocking.TrackerLog
import mozilla.components.support.ktx.kotlin.tryGetHostFromUrl
import org.mozilla.fenix.R
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.databinding.ComponentTrackingProtectionPanelBinding
import org.mozilla.fenix.ext.addUnderline
import org.mozilla.fenix.ext.metrics
import org.mozilla.fenix.trackingprotection.TrackingProtectionCategory.CROSS_SITE_TRACKING_COOKIES
import org.mozilla.fenix.trackingprotection.TrackingProtectionCategory.CRYPTOMINERS
Expand Down Expand Up @@ -53,6 +58,11 @@ interface TrackingProtectionPanelViewInteractor {
* @param categoryBlocked The trackers from this category were blocked
*/
fun openDetails(category: TrackingProtectionCategory, categoryBlocked: Boolean)

/**
* Called when the Learn more link for SmartBlock is clicked.
*/
fun onLearnMoreClicked()
}

/**
Expand Down Expand Up @@ -126,10 +136,28 @@ class TrackingProtectionPanelView(
category: TrackingProtectionCategory,
categoryBlocked: Boolean
) {
val containASmartBlockItem = bucketedTrackers.get(category, categoryBlocked).any { it.unBlockedBySmartBlock }
binding.normalMode.visibility = View.GONE
binding.detailsMode.visibility = View.VISIBLE
binding.categoryTitle.setText(category.title)
binding.blockingTextList.text = bucketedTrackers.get(category, categoryBlocked).joinToString("\n")

binding.smartblockDescription.isVisible = containASmartBlockItem
binding.smartblockLearnMore.isVisible = containASmartBlockItem

val trackersList = bucketedTrackers.get(category, categoryBlocked).joinToString("<br/>") {
createTrackerItem(it, containASmartBlockItem)
}

binding.blockingTextList.text = HtmlCompat.fromHtml(trackersList, HtmlCompat.FROM_HTML_MODE_COMPACT)

// show description for SmartBlock tracking content in details
if (containASmartBlockItem) {
with(binding.smartblockLearnMore) {
movementMethod = LinkMovementMethod.getInstance()
addUnderline()
setOnClickListener { interactor.onLearnMoreClicked() }
}
}
binding.categoryDescription.setText(category.description)
binding.detailsBlockingHeader.setText(
if (categoryBlocked) {
Expand All @@ -143,6 +171,15 @@ class TrackingProtectionPanelView(
binding.detailsBack.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED)
}

private fun createTrackerItem(tracker: TrackerLog, isUnblockedSection: Boolean): String {
val space = if (isUnblockedSection) "&nbsp;&nbsp;" else ""
return if (tracker.unBlockedBySmartBlock) {
"<b>*${tracker.url.tryGetHostFromUrl()}</b>"
} else {
"$space${tracker.url.tryGetHostFromUrl()}"
}
}

/**
* Will force accessibility focus to last entered details category.
* Called when user returns from details_mode.
Expand Down
72 changes: 51 additions & 21 deletions app/src/main/res/layout/component_tracking_protection_panel.xml
Original file line number Diff line number Diff line change
Expand Up @@ -242,40 +242,70 @@
app:layout_constraintTop_toBottomOf="@id/category_title"
tools:text="@tools:sample/lorem" />

<TextView
android:id="@+id/smartblock_description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="52dp"
android:layout_marginEnd="19dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:textColor="?secondaryText"
android:drawablePadding="16dp"
app:drawableTint="?accent"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/category_description"
android:text="@string/preference_etp_smartblock_description" />

<org.mozilla.fenix.utils.LinkTextView
android:id="@+id/smartblock_learn_more"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/preference_etp_smartblock_learn_more"
android:textColor="?accent"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@id/smartblock_description"
app:layout_constraintTop_toBottomOf="@id/smartblock_description" />

<View
android:id="@+id/line_divider_details"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="12dp"
android:layout_marginBottom="8dp"
android:background="?neutralFaded"
app:layout_constraintTop_toBottomOf="@id/category_description" />

<TextView
android:id="@+id/details_blocking_header"
android:accessibilityHeading="true"
style="@style/QuickSettingsText"
android:layout_width="wrap_content"
android:layout_height="@dimen/tracking_protection_item_height"
android:layout_marginStart="52dp"
android:layout_marginEnd="26dp"
android:paddingStart="0dp"
android:paddingEnd="0dp"
android:text="@string/enhanced_tracking_protection_blocked"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/line_divider_details"
tools:targetApi="p" />
app:layout_constraintTop_toBottomOf="@id/smartblock_learn_more" />

<androidx.core.widget.NestedScrollView
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/blocking_scrollview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true"
android:scrollbars="vertical"
android:orientation="vertical"
android:isScrollContainer="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@id/details_blocking_header"
app:layout_constraintTop_toBottomOf="@id/details_blocking_header">
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/line_divider_details">

<TextView
android:id="@+id/details_blocking_header"
android:accessibilityHeading="true"
style="@style/QuickSettingsText"
android:layout_width="wrap_content"
android:layout_height="@dimen/tracking_protection_item_height"
android:layout_marginStart="52dp"
android:layout_marginEnd="26dp"
android:paddingStart="0dp"
android:paddingEnd="0dp"
android:text="@string/enhanced_tracking_protection_blocked"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/blocking_scrollview"
tools:targetApi="p" />

<TextView
android:id="@+id/blocking_text_list"
Expand All @@ -286,6 +316,6 @@
android:lineSpacingMultiplier="1.2"
android:layout_marginBottom="12dp"
tools:text="@tools:sample/lorem/random" />
</androidx.core.widget.NestedScrollView>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
4 changes: 4 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1439,6 +1439,10 @@
<string name="etp_redirect_trackers_title">Redirect Trackers</string>
<!-- Description of redirect tracker cookies that can be blocked by Enhanced Tracking Protection -->
<string name="etp_redirect_trackers_description">Clears cookies set by redirects to known tracking websites.</string>
<!-- Description of the SmartBlock Enhanced Tracking Protection feature -->
<string name="preference_etp_smartblock_description">Some trackers marked below have been partially unblocked on this page because you interacted with them *.</string>
<!-- Text displayed that links to website about enhanced tracking protection SmartBlock -->
<string name="preference_etp_smartblock_learn_more">Learn more</string>

<!-- About page link text to open support link -->
<string name="about_support">Support</string>
Expand Down
Loading

0 comments on commit cbb8f80

Please sign in to comment.