For #1084 - Add tracking protection toggle to quick settings dialog

nightly-build-test
Emily Kager 5 years ago committed by Colin Lee
parent 3f906dc58a
commit 01a181975d

@ -517,10 +517,14 @@ class BrowserFragment : Fragment(), BackHandler, CoroutineScope {
val quickSettingsSheet = QuickSettingsSheetDialogFragment.newInstance(
url = session.url,
isSecured = session.securityInfo.secure,
isTrackingProtectionOn = Settings.getInstance(context!!).shouldUseTrackingProtection,
sitePermissions = sitePermissions
)
quickSettingsSheet.sitePermissions = sitePermissions
quickSettingsSheet.show(requireFragmentManager(), QuickSettingsSheetDialogFragment.FRAGMENT_TAG)
quickSettingsSheet.show(
requireFragmentManager(),
QuickSettingsSheetDialogFragment.FRAGMENT_TAG
)
}
}
}
@ -572,6 +576,6 @@ class BrowserFragment : Fragment(), BackHandler, CoroutineScope {
private const val REQUEST_CODE_PROMPT_PERMISSIONS = 2
private const val REQUEST_CODE_APP_PERMISSIONS = 3
private const val TOOLBAR_HEIGHT = 56f
private const val REPORT_SITE_ISSUE_URL = "https://webcompat.com/issues/new?url=%s&label=browser-fenix"
const val REPORT_SITE_ISSUE_URL = "https://webcompat.com/issues/new?url=%s&label=browser-fenix"
}
}

@ -80,6 +80,16 @@ class SettingsFragment : PreferenceFragmentCompat(), CoroutineScope, AccountObse
requireComponents.search.searchEngineManager.getDefaultSearchEngine(it).name
}
val trackingProtectionPreference =
findPreference<Preference>(getString(R.string.pref_key_tracking_protection_settings))
trackingProtectionPreference?.summary = context?.let {
if (org.mozilla.fenix.utils.Settings.getInstance(it).shouldUseTrackingProtection) {
getString(R.string.tracking_protection_on)
} else {
getString(R.string.tracking_protection_off)
}
}
val themesPreference =
findPreference<Preference>(getString(R.string.pref_key_theme))
themesPreference?.summary = context?.let {

@ -9,6 +9,7 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.getPreferenceKey
import org.mozilla.fenix.ext.requireComponents
@ -40,6 +41,7 @@ class TrackingProtectionFragment : PreferenceFragmentCompat() {
sessions.forEach { getEngineSession(it)?.enableTrackingProtection(policy) }
}
}
requireContext().components.useCases.sessionUseCases.reload.invoke()
true
}

@ -35,6 +35,7 @@ class QuickSettingsComponent(
mode = QuickSettingsState.Mode.Normal(
change.url,
change.isSecured,
change.isTrackingProtectionOn,
change.sitePermissions
)
)
@ -97,15 +98,27 @@ class QuickSettingsComponent(
data class QuickSettingsState(val mode: Mode) : ViewState {
sealed class Mode {
data class Normal(val url: String, val isSecured: Boolean, val sitePermissions: SitePermissions?) : Mode()
data class ActionLabelUpdated(val phoneFeature: PhoneFeature, val sitePermissions: SitePermissions?) :
data class Normal(
val url: String,
val isSecured: Boolean,
val isTrackingProtectionOn: Boolean,
val sitePermissions: SitePermissions?
) : Mode()
data class ActionLabelUpdated(
val phoneFeature: PhoneFeature,
val sitePermissions: SitePermissions?
) :
Mode()
data class CheckPendingFeatureBlockedByAndroid(val sitePermissions: SitePermissions?) : Mode()
data class CheckPendingFeatureBlockedByAndroid(val sitePermissions: SitePermissions?) :
Mode()
}
}
sealed class QuickSettingsAction : Action {
data class SelectReportProblem(val url: String) : QuickSettingsAction()
data class ToggleTrackingProtection(val trackingProtection: Boolean) : QuickSettingsAction()
data class SelectBlockedByAndroid(val permissions: Array<String>) : QuickSettingsAction()
data class TogglePermission(val featurePhone: PhoneFeature) : QuickSettingsAction()
}
@ -114,6 +127,7 @@ sealed class QuickSettingsChange : Change {
data class Change(
val url: String,
val isSecured: Boolean,
val isTrackingProtectionOn: Boolean,
val sitePermissions: SitePermissions?
) : QuickSettingsChange()

@ -10,6 +10,7 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.preference.PreferenceManager
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@ -17,7 +18,9 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import mozilla.components.feature.sitepermissions.SitePermissions
import org.mozilla.fenix.R
import org.mozilla.fenix.browser.BrowserFragment
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.mvi.ActionBusFactory
import org.mozilla.fenix.mvi.getAutoDisposeObservable
import org.mozilla.fenix.mvi.getManagedEmitter
@ -27,6 +30,7 @@ import kotlin.coroutines.CoroutineContext
private const val KEY_URL = "KEY_URL"
private const val KEY_IS_SECURED = "KEY_IS_SECURED"
private const val KEY_SITE_PERMISSIONS = "KEY_SITE_PERMISSIONS"
private const val KEY_IS_TP_ON = "KEY_IS_TP_ON"
private const val REQUEST_CODE_QUICK_SETTINGS_PERMISSIONS = 4
@SuppressWarnings("TooManyFunctions")
@ -34,6 +38,7 @@ class QuickSettingsSheetDialogFragment : BottomSheetDialogFragment(), CoroutineS
private val safeArguments get() = requireNotNull(arguments)
private val url: String by lazy { safeArguments.getString(KEY_URL) }
private val isSecured: Boolean by lazy { safeArguments.getBoolean(KEY_IS_SECURED) }
private val isTrackingProtectionOn: Boolean by lazy { safeArguments.getBoolean(KEY_IS_TP_ON) }
private lateinit var quickSettingsComponent: QuickSettingsComponent
private lateinit var job: Job
@ -59,7 +64,7 @@ class QuickSettingsSheetDialogFragment : BottomSheetDialogFragment(), CoroutineS
quickSettingsComponent = QuickSettingsComponent(
rootView as ConstraintLayout, ActionBusFactory.get(this),
QuickSettingsState(
QuickSettingsState.Mode.Normal(url, isSecured, sitePermissions)
QuickSettingsState.Mode.Normal(url, isSecured, isTrackingProtectionOn, sitePermissions)
)
)
}
@ -70,6 +75,7 @@ class QuickSettingsSheetDialogFragment : BottomSheetDialogFragment(), CoroutineS
fun newInstance(
url: String,
isSecured: Boolean,
isTrackingProtectionOn: Boolean,
sitePermissions: SitePermissions?
): QuickSettingsSheetDialogFragment {
@ -79,6 +85,7 @@ class QuickSettingsSheetDialogFragment : BottomSheetDialogFragment(), CoroutineS
with(arguments) {
putString(KEY_URL, url)
putBoolean(KEY_IS_SECURED, isSecured)
putBoolean(KEY_IS_TP_ON, isTrackingProtectionOn)
putParcelable(KEY_SITE_PERMISSIONS, sitePermissions)
}
fragment.arguments = arguments
@ -110,6 +117,37 @@ class QuickSettingsSheetDialogFragment : BottomSheetDialogFragment(), CoroutineS
is QuickSettingsAction.SelectBlockedByAndroid -> {
requestPermissions(it.permissions, REQUEST_CODE_QUICK_SETTINGS_PERMISSIONS)
}
is QuickSettingsAction.SelectReportProblem -> {
launch(Dispatchers.Main) {
val reportUrl =
String.format(BrowserFragment.REPORT_SITE_ISSUE_URL, it.url)
requireComponents.useCases.sessionUseCases.loadUrl.invoke(reportUrl)
}
}
is QuickSettingsAction.ToggleTrackingProtection -> {
val trackingEnabled = it.trackingProtection
with(requireComponents.core) {
val policy =
createTrackingProtectionPolicy(trackingEnabled)
PreferenceManager.getDefaultSharedPreferences(context).edit()
.putBoolean(
context!!.getString(R.string.pref_key_tracking_protection),
trackingEnabled
).apply()
engine.settings.trackingProtectionPolicy = policy
with(sessionManager) {
sessions.forEach {
getEngineSession(it)?.enableTrackingProtection(
policy
)
}
}
}
launch(Dispatchers.Main) {
requireContext().components.useCases.sessionUseCases.reload.invoke()
}
}
is QuickSettingsAction.TogglePermission -> {
launch {

@ -8,6 +8,7 @@ import android.view.View
import android.view.View.GONE
import android.view.View.VISIBLE
import android.view.ViewGroup
import android.widget.Switch
import android.widget.TextView
import androidx.appcompat.content.res.AppCompatResources
import androidx.appcompat.widget.AppCompatTextView
@ -19,6 +20,7 @@ import mozilla.components.feature.sitepermissions.SitePermissions
import mozilla.components.feature.sitepermissions.SitePermissions.Status.NO_DECISION
import mozilla.components.support.ktx.android.net.hostWithoutCommonPrefixes
import mozilla.components.support.ktx.kotlin.toUri
import org.mozilla.fenix.DefaultThemeManager
import org.mozilla.fenix.R
import org.mozilla.fenix.mvi.UIView
import org.mozilla.fenix.settings.PhoneFeature
@ -28,6 +30,7 @@ import org.mozilla.fenix.settings.PhoneFeature.MICROPHONE
import org.mozilla.fenix.settings.PhoneFeature.NOTIFICATION
import org.mozilla.fenix.utils.Settings
@Suppress("TooManyFunctions")
class QuickSettingsUIView(
container: ViewGroup,
actionEmitter: Observer<QuickSettingsAction>,
@ -38,6 +41,8 @@ class QuickSettingsUIView(
) {
private val securityInfoLabel: TextView
private val urlLabel: TextView
private val trackingProtectionSwitch: Switch
private val reportProblemAction: TextView
private val cameraActionLabel: TextView
private val cameraLabel: TextView
private val microphoneActionLabel: TextView
@ -53,6 +58,8 @@ class QuickSettingsUIView(
init {
urlLabel = view.findViewById<AppCompatTextView>(R.id.url)
securityInfoLabel = view.findViewById<AppCompatTextView>(R.id.security_info)
trackingProtectionSwitch = view.findViewById(R.id.tracking_protection)
reportProblemAction = view.findViewById(R.id.report_problem)
cameraActionLabel = view.findViewById<AppCompatTextView>(R.id.camera_action_label)
cameraLabel = view.findViewById<AppCompatTextView>(R.id.camera_icon)
microphoneActionLabel = view.findViewById<AppCompatTextView>(R.id.microphone_action_label)
@ -68,6 +75,8 @@ class QuickSettingsUIView(
is QuickSettingsState.Mode.Normal -> {
bindUrl(state.mode.url)
bindSecurityInfo(state.mode.isSecured)
bindReportProblemAction(state.mode.url)
bindTrackingProtectionInfo(state.mode.isTrackingProtectionOn)
bindPhoneFeatureItem(cameraActionLabel, CAMERA, state.mode.sitePermissions)
bindPhoneFeatureItem(microphoneActionLabel, MICROPHONE, state.mode.sitePermissions)
bindPhoneFeatureItem(notificationActionLabel, NOTIFICATION, state.mode.sitePermissions)
@ -90,6 +99,38 @@ class QuickSettingsUIView(
urlLabel.text = url.toUri().hostWithoutCommonPrefixes
}
private fun bindTrackingProtectionInfo(isTrackingProtectionOn: Boolean) {
val drawableId =
if (isTrackingProtectionOn) R.drawable.ic_tracking_protection else
R.drawable.ic_tracking_protection_disabled
val drawableTint = if (isTrackingProtectionOn) DefaultThemeManager.resolveAttribute(
R.attr.primaryText,
context
) else DefaultThemeManager.resolveAttribute(R.attr.neutral, context)
val icon = AppCompatResources.getDrawable(context, drawableId)
val resolvedColor = ContextCompat.getColor(context, drawableTint)
icon?.setTint(resolvedColor)
trackingProtectionSwitch.setTextColor(resolvedColor)
trackingProtectionSwitch.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null)
trackingProtectionSwitch.isChecked = isTrackingProtectionOn
trackingProtectionSwitch.setOnCheckedChangeListener { _, isChecked ->
actionEmitter.onNext(
QuickSettingsAction.ToggleTrackingProtection(
isChecked
)
)
}
}
private fun bindReportProblemAction(url: String) {
reportProblemAction.setOnClickListener {
actionEmitter.onNext(
QuickSettingsAction.SelectReportProblem(url)
)
}
}
private fun bindSecurityInfo(isSecured: Boolean) {
val stringId: Int
val drawableId: Int

@ -0,0 +1,14 @@
<?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/. -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?primaryText"
android:fillType="evenOdd"
android:pathData="M17.9,10.825C17.92,10.583 17.939,10.228 17.955,9.8L19.994,7.757C19.988,8.963 19.958,10.284 19.888,11.017C19.584,14.191 18.966,15.932 17.437,17.911C16.1139,19.5759 14.209,20.6776 12.106,20.994L12,21.006L11.893,20.994C10.5742,20.796 9.3208,20.2893 8.235,19.515L9.683,18.067C10.3916,18.5151 11.1773,18.8277 12,18.989C13.5187,18.7058 14.8864,17.8899 15.857,16.688C17.153,15.01 17.631,13.641 17.9,10.825ZM20.207,3.793C20.5973,4.1812 20.6005,4.8119 20.214,5.204L5.214,20.204C4.9629,20.464 4.5911,20.5682 4.2415,20.4767C3.8919,20.3852 3.6188,20.1121 3.5273,19.7625C3.4358,19.4129 3.54,19.0411 3.8,18.79L5.8,16.79C4.7719,15.0326 4.1919,13.0494 4.111,11.015C4.012,9.973 4,7.767 4,6.1C4.0096,5.0498 4.7782,4.161 5.816,4L12,2.986L18.187,3.999C18.2894,4.0247 18.3897,4.0581 18.487,4.099L18.793,3.793C19.1835,3.4026 19.8165,3.4026 20.207,3.793ZM6.1,10.826C6.1631,12.3919 6.5575,13.9266 7.257,15.329L8.717,13.864C8.3635,12.8432 8.1528,11.7785 8.091,10.7C8.066,10.439 8.015,9.667 8,7.7L12,7.041L12,10.586L16.789,5.797L12,5.014L6.138,5.972C6.0646,5.9767 6.0058,6.0347 6,6.108C6,8.4 6.031,10.076 6.1,10.826Z" />
</vector>

@ -35,14 +35,48 @@
app:layout_constraintTop_toBottomOf="@id/url"/>
<View
android:id="@+id/line_divider"
android:layout_width="match_parent"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:layout_height="1dp"
android:background="?neutral"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/security_info"/>
android:id="@+id/line_divider_security"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:background="?neutral"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/security_info" />
<Switch
android:id="@+id/tracking_protection"
style="@style/QuickSettingsText.Icon"
android:layout_width="match_parent"
android:layout_height="@dimen/quicksettings_item_height"
android:drawableStart="@drawable/ic_tracking_protection"
android:paddingEnd="24dp"
android:text="@string/preferences_tracking_protection"
app:layout_constraintBottom_toTopOf="@id/report_problem"
app:layout_constraintTop_toBottomOf="@id/line_divider_security" />
<TextView
android:id="@+id/report_problem"
style="@style/QuickSettingsText.Icon"
android:layout_width="match_parent"
android:layout_height="@dimen/quicksettings_item_height"
android:gravity="top"
android:paddingStart="48dp"
android:text="@string/tracking_protection_report_problem"
android:textColor="?accentBright"
android:textSize="12sp"
app:layout_constraintBottom_toTopOf="@id/line_divider"
app:layout_constraintTop_toBottomOf="@id/tracking_protection" />
<View
android:id="@+id/line_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:background="?neutral"
app:layout_constraintBottom_toTopOf="@id/camera_icon"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/camera_icon"

@ -386,4 +386,10 @@
<string name="phone_feature_blocked_by_android">Blocked by Android</string>
<!-- Preference for showing a list of websites that the default configurations won't apply to them -->
<string name="preference_exceptions">Exceptions</string>
<!-- Action in Quick Settings dialog to report a site problem related to tracking protection -->
<string name="tracking_protection_report_problem">Report a problem</string>
<!-- Summary of tracking protection preference if tracking protection is set to on -->
<string name="tracking_protection_on">On</string>
<!-- Summary of tracking protection preference if tracking protection is set to off -->
<string name="tracking_protection_off">Off</string>
</resources>

Loading…
Cancel
Save